<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>用户环境管理系统</title>
    <style>
        :root {
            --primary-color: #6366f1;
            --primary-hover: #4f46e5;
            --success-color: #10b981;
            --success-hover: #059669;
            --warning-color: #f59e0b;
            --warning-hover: #d97706;
            --danger-color: #ef4444;
            --danger-hover: #dc2626;
            --info-color: #06b6d4;
            --info-hover: #0891b2;
            --secondary-color: #6b7280;
            --secondary-hover: #4b5563;
            --bg-primary: #ffffff;
            --bg-secondary: #f8fafc;
            --bg-tertiary: #f1f5f9;
            --text-primary: #1e293b;
            --text-secondary: #475569;
            --text-muted: #64748b;
            --border-color: #e2e8f0;
            --border-hover: #cbd5e1;
            --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
            --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
            --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
            --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
            --radius-sm: 0.375rem;
            --radius-md: 0.5rem;
            --radius-lg: 0.75rem;
            --radius-xl: 1rem;
        }

        * {
            box-sizing: border-box;
        }

        body {
            font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
            margin: 0;
            padding: 0;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            color: var(--text-primary);
            line-height: 1.6;
        }

        .container {
            max-width: 1400px;
            margin: 0 auto;
            padding: 20px;
        }
        .header {
            text-align: center;
            margin-bottom: 2rem;
            color: white;
        }

        .header h1 {
            font-size: 2.5rem;
            font-weight: 800;
            margin: 0;
            text-shadow: 0 2px 4px rgba(0,0,0,0.3);
            background: linear-gradient(45deg, #fff, #f0f9ff);
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
        }

        .header p {
            font-size: 1.1rem;
            opacity: 0.9;
            margin: 0.5rem 0 0 0;
        }

        .main-content {
            background: var(--bg-primary);
            border-radius: var(--radius-xl);
            box-shadow: var(--shadow-xl);
            overflow: hidden;
            backdrop-filter: blur(10px);
            background: rgba(255, 255, 255, 0.95);
        }

        .content-wrapper {
            padding: 2rem;
        }

        .section {
            margin-bottom: 30px;
            padding: 20px;
            border: 1px solid var(--border-color);
            border-radius: var(--radius-md);
        }

        .section h2 {
            color: var(--text-primary);
            margin-top: 0;
        }
        .form-group {
            margin-bottom: 1.25rem;
        }

        .form-group h3 {
            color: var(--text-primary);
            margin: 0 0 1rem 0;
            font-size: 1.1rem;
            font-weight: 600;
            display: flex;
            align-items: center;
            gap: 0.5rem;
        }

        label {
            display: block;
            margin-bottom: 0.5rem;
            font-weight: 600;
            color: var(--text-secondary);
            font-size: 0.9rem;
        }

        input, select, textarea {
            width: 100%;
            padding: 0.75rem 1rem;
            border: 2px solid var(--border-color);
            border-radius: var(--radius-md);
            font-size: 0.95rem;
            transition: all 0.3s ease;
            background: var(--bg-primary);
            color: var(--text-primary);
        }

        input:focus, select:focus, textarea:focus {
            outline: none;
            border-color: var(--primary-color);
            box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
        }

        input:hover, select:hover, textarea:hover {
            border-color: var(--border-hover);
        }

        /* 按钮样式 */
        button {
            padding: 0.75rem 1.5rem;
            border: none;
            border-radius: var(--radius-md);
            font-size: 0.95rem;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s ease;
            display: inline-flex;
            align-items: center;
            justify-content: center;
            gap: 0.5rem;
            text-decoration: none;
            position: relative;
            overflow: hidden;
        }

        button::before {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            width: 0;
            height: 0;
            background: rgba(255,255,255,0.2);
            border-radius: 50%;
            transition: all 0.3s ease;
            transform: translate(-50%, -50%);
        }

        button:hover::before {
            width: 300px;
            height: 300px;
        }

        button:active {
            transform: translateY(1px);
        }

        .btn-primary {
            background: var(--primary-color);
            color: white;
        }

        .btn-primary:hover {
            background: var(--primary-hover);
            transform: translateY(-2px);
            box-shadow: var(--shadow-lg);
        }

        .btn-success {
            background: var(--success-color);
            color: white;
        }

        .btn-success:hover {
            background: var(--success-hover);
            transform: translateY(-2px);
            box-shadow: var(--shadow-lg);
        }

        .btn-warning {
            background: var(--warning-color);
            color: white;
        }

        .btn-warning:hover {
            background: var(--warning-hover);
            transform: translateY(-2px);
            box-shadow: var(--shadow-lg);
        }

        .btn-danger {
            background: var(--danger-color);
            color: white;
        }

        .btn-danger:hover {
            background: var(--danger-hover);
            transform: translateY(-2px);
            box-shadow: var(--shadow-lg);
        }

        .btn-info {
            background: var(--info-color);
            color: white;
        }

        .btn-info:hover {
            background: var(--info-hover);
            transform: translateY(-2px);
            box-shadow: var(--shadow-lg);
        }

        .btn-secondary {
            background: var(--secondary-color);
            color: white;
        }

        .btn-secondary:hover {
            background: var(--secondary-hover);
            transform: translateY(-2px);
            box-shadow: var(--shadow-lg);
        }
        .button-group {
            display: flex;
            gap: 0.75rem;
            margin-top: 1rem;
            flex-wrap: wrap;
        }

        .button-group button {
            flex: 1;
            min-width: 120px;
        }

        .user-list {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
            gap: 1.5rem;
            margin-top: 1.5rem;
        }

        .user-card {
            border: 1px solid var(--border-color);
            border-radius: var(--radius-lg);
            padding: 1.5rem;
            background: var(--bg-primary);
            transition: all 0.3s ease;
            box-shadow: var(--shadow-sm);
            position: relative;
            overflow: hidden;
        }

        .user-card::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            height: 4px;
            background: linear-gradient(90deg, var(--primary-color), var(--success-color), var(--info-color));
        }

        .user-card:hover {
            transform: translateY(-5px);
            box-shadow: var(--shadow-lg);
            border-color: var(--primary-color);
        }

        .user-card h3 {
            margin: 0 0 1rem 0;
            color: var(--text-primary);
            font-size: 1.25rem;
            font-weight: 600;
        }

        .user-card p {
            margin: 0.5rem 0;
            color: var(--text-secondary);
            font-size: 0.9rem;
        }

        .user-card strong {
            color: var(--text-primary);
            font-weight: 600;
        }

        .file-tree-container {
            max-height: 500px;
            overflow-y: auto;
            border: 1px solid var(--border-color);
            border-radius: var(--radius-md);
            padding: 1rem;
            background: var(--bg-secondary);
            margin-top: 1rem;
        }

        .file-tree-node {
            display: flex;
            align-items: center;
            font-size: 0.9rem;
            padding: 0.5rem;
            margin: 0.25rem 0;
            border-radius: var(--radius-sm);
            cursor: pointer;
            transition: all 0.2s ease;
        }

        .file-tree-node:hover {
            background: rgba(99, 102, 241, 0.1);
        }
        
        /* 可折叠区域样式 */
        .collapsible-section {
            border: 1px solid var(--border-color);
            border-radius: var(--radius-lg);
            margin-bottom: 1.5rem;
            overflow: hidden;
            transition: all 0.3s ease;
            box-shadow: var(--shadow-sm);
        }

        .collapsible-section:hover {
            box-shadow: var(--shadow-md);
            border-color: var(--border-hover);
        }

        .collapsible-header {
            background: linear-gradient(135deg, var(--bg-secondary) 0%, var(--bg-tertiary) 100%);
            padding: 1.25rem 1.5rem;
            cursor: pointer;
            display: flex;
            justify-content: space-between;
            align-items: center;
            border-bottom: 1px solid var(--border-color);
            transition: all 0.3s ease;
            user-select: none;
        }

        .collapsible-header:hover {
            background: linear-gradient(135deg, var(--bg-tertiary) 0%, var(--border-color) 100%);
        }

        .collapsible-header h2 {
            margin: 0;
            color: var(--text-primary);
            font-size: 1.25rem;
            font-weight: 600;
            display: flex;
            align-items: center;
            gap: 0.5rem;
        }

        .collapsible-toggle {
            font-size: 1.25rem;
            color: var(--text-secondary);
            transition: all 0.3s ease;
            width: 24px;
            height: 24px;
            display: flex;
            align-items: center;
            justify-content: center;
            border-radius: 50%;
            background: rgba(255,255,255,0.5);
        }

        .collapsible-header:hover .collapsible-toggle {
            background: rgba(255,255,255,0.8);
            color: var(--primary-color);
        }

        .collapsible-content {
            padding: 1.5rem;
            background: var(--bg-primary);
            transition: all 0.3s ease;
            max-height: 2000px;
            opacity: 1;
        }

        .collapsible-content.collapsed {
            max-height: 0;
            opacity: 0;
            padding: 0 1.5rem;
            overflow: hidden;
        }

        .collapsible-toggle.rotated {
            transform: rotate(180deg);
        }
        .file-tree-node {
            display: flex;
            align-items: center;
            font-size: 14px;
        }
        .file-tree-node:hover {
            background-color: #e9ecef;
        }
        .file-tree-node.directory {
            font-weight: bold;
            color: #007bff;
        }
        .file-tree-node.file {
            color: #333;
        }
        .file-tree-node.file.code {
            color: #28a745;
        }
        .file-tree-node.file.document {
            color: #17a2b8;
        }
        .file-tree-node.file.image {
            color: #fd7e14;
        }
        .file-tree-node.file.other {
            color: #6c757d;
        }
        .file-tree-indent {
            margin-left: 20px;
        }
        .file-tree-icon {
            margin-right: 5px;
            font-size: 12px;
        }
        .file-tree-details {
            font-size: 12px;
            color: #666;
            margin-left: 10px;
        }
        .file-tree-loading {
            text-align: center;
            padding: 20px;
            color: #666;
        }
        .file-tree-error {
            color: #dc3545;
            padding: 10px;
            background: #f8d7da;
            border-radius: 4px;
            margin-top: 10px;
        }
        .user-card {
            border: 1px solid #ddd;
            border-radius: 5px;
            padding: 15px;
            background: #f9f9f9;
        }
        .user-card h3 {
            margin-top: 0;
            color: #333;
        }
        .status {
            display: inline-block;
            padding: 0.25rem 0.75rem;
            border-radius: var(--radius-sm);
            font-size: 0.75rem;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.05em;
        }

        .status.running {
            background: rgba(16, 185, 129, 0.1);
            color: var(--success-color);
            border: 1px solid rgba(16, 185, 129, 0.2);
        }

        .status.stopped {
            background: rgba(239, 68, 68, 0.1);
            color: var(--danger-color);
            border: 1px solid rgba(239, 68, 68, 0.2);
        }

        .status.error {
            background: rgba(245, 158, 11, 0.1);
            color: var(--warning-color);
            border: 1px solid rgba(245, 158, 11, 0.2);
        }
        .button-group {
            display: flex;
            gap: 5px;
            margin-top: 10px;
        }
        .button-group button {
            flex: 1;
            padding: 5px 10px;
            font-size: 12px;
        }
        .stats {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 1.5rem;
            margin-bottom: 2rem;
        }

        .stat-card {
            background: linear-gradient(135deg, var(--primary-color) 0%, var(--info-color) 100%);
            color: white;
            padding: 1.5rem;
            border-radius: var(--radius-lg);
            text-align: center;
            transition: all 0.3s ease;
            box-shadow: var(--shadow-md);
            position: relative;
            overflow: hidden;
        }

        .stat-card::before {
            content: '';
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
            transition: left 0.5s;
        }

        .stat-card:hover::before {
            left: 100%;
        }

        .stat-card:hover {
            transform: translateY(-5px);
            box-shadow: var(--shadow-xl);
        }

        .stat-number {
            font-size: 2.5rem;
            font-weight: 800;
            margin-bottom: 0.5rem;
            text-shadow: 0 2px 4px rgba(0,0,0,0.3);
        }

        .stat-label {
            font-size: 0.9rem;
            opacity: 0.9;
            font-weight: 500;
        }
        .message {
            padding: 1rem 1.5rem;
            margin: 1rem 0;
            border-radius: var(--radius-md);
            border-left: 4px solid;
            font-weight: 500;
            animation: slideIn 0.3s ease;
        }

        @keyframes slideIn {
            from {
                opacity: 0;
                transform: translateX(-20px);
            }
            to {
                opacity: 1;
                transform: translateX(0);
            }
        }

        .message.success {
            background: rgba(16, 185, 129, 0.1);
            color: var(--success-color);
            border-left-color: var(--success-color);
        }

        .message.error {
            background: rgba(239, 68, 68, 0.1);
            color: var(--danger-color);
            border-left-color: var(--danger-color);
        }

        /* 模态对话框样式 */
        .modal {
            display: none;
            position: fixed;
            z-index: 9999;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.5);
            backdrop-filter: blur(5px);
        }

        .modal-content {
            background-color: #ffffff;
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            padding: 0;
            border-radius: 8px;
            width: 90%;
            max-width: 500px;
            box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
            border: 1px solid #e5e7eb;
            animation: modalSlideIn 0.3s ease;
            z-index: 10000;
        }

        @keyframes modalSlideIn {
            from {
                opacity: 0;
                transform: translateY(-50px) scale(0.9);
            }
            to {
                opacity: 1;
                transform: translateY(0) scale(1);
            }
        }

        .modal-header {
            padding: 1.5rem 1.5rem 1rem;
            border-bottom: 1px solid var(--border-color);
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .modal-header h3 {
            margin: 0;
            color: var(--text-primary);
            font-size: 1.25rem;
        }

        .close {
            color: var(--text-muted);
            font-size: 1.5rem;
            font-weight: bold;
            cursor: pointer;
            transition: color 0.2s ease;
        }

        .close:hover {
            color: var(--text-primary);
        }

        .modal-body {
            padding: 1.5rem;
        }

        .modal-body p {
            margin: 0 0 1rem 0;
            color: var(--text-muted);
        }

        .modal-footer {
            padding: 1rem 1.5rem 1.5rem;
            border-top: 1px solid var(--border-color);
            display: flex;
            gap: 0.75rem;
            justify-content: flex-end;
        }

        .message.info {
            background: rgba(6, 182, 212, 0.1);
            color: var(--info-color);
            border-left-color: var(--info-color);
        }
        .env-type {
            display: inline-block;
            padding: 0.25rem 0.5rem;
            border-radius: var(--radius-sm);
            font-size: 0.7rem;
            font-weight: 600;
            margin-left: 0.5rem;
            text-transform: uppercase;
            letter-spacing: 0.05em;
        }

        .env-type.ide {
            background: rgba(99, 102, 241, 0.1);
            color: var(--primary-color);
            border: 1px solid rgba(99, 102, 241, 0.2);
        }

        .env-type.jupyter {
            background: rgba(245, 158, 11, 0.1);
            color: var(--warning-color);
            border: 1px solid rgba(245, 158, 11, 0.2);
        }

        .env-type.virtual_desktop {
            background: rgba(6, 182, 212, 0.1);
            color: var(--info-color);
            border: 1px solid rgba(6, 182, 212, 0.2);
        }

        .env-type.redis {
            background: rgba(239, 68, 68, 0.1);
            color: var(--danger-color);
            border: 1px solid rgba(239, 68, 68, 0.2);
        }

        .env-type.mysql {
            background: rgba(16, 185, 129, 0.1);
            color: var(--success-color);
            border: 1px solid rgba(16, 185, 129, 0.2);
        }

        .env-type.rabbitmq {
            background: rgba(245, 158, 11, 0.1);
            color: var(--warning-color);
            border: 1px solid rgba(245, 158, 11, 0.2);
        }

        .env-type.elasticsearch {
            background: rgba(139, 92, 246, 0.1);
            color: #8b5cf6;
            border: 1px solid rgba(139, 92, 246, 0.2);
        }

        .env-type.both {
            background: rgba(16, 185, 129, 0.1);
            color: var(--success-color);
            border: 1px solid rgba(16, 185, 129, 0.2);
        }

        .env-type.full_stack {
            background: rgba(99, 102, 241, 0.1);
            color: var(--primary-color);
            border: 1px solid rgba(99, 102, 241, 0.2);
        }

        /* 进度条样式 */
        .progress-container {
            display: flex;
            align-items: center;
            gap: 10px;
        }

        .progress-bar {
            flex: 1;
            height: 8px;
            background: var(--bg-primary);
            border-radius: 4px;
            overflow: hidden;
            border: 1px solid var(--border-color);
        }

        .progress-fill {
            height: 100%;
            background: linear-gradient(90deg, var(--primary-color), var(--info-color));
            width: 0%;
            transition: width 0.3s ease;
            border-radius: 3px;
        }

        .progress-text {
            min-width: 40px;
            font-size: 0.8em;
            font-weight: 600;
            color: var(--text-primary);
        }

        /* 环境创建进度样式 */
        .environment-progress {
            animation: slideInUp 0.3s ease;
        }

        @keyframes slideInUp {
            from {
                opacity: 0;
                transform: translateY(20px);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }
        .user-card a {
            color: #007bff;
            text-decoration: none;
            font-size: 0.9em;
        }
        .user-card a:hover {
            text-decoration: underline;
        }
        .quick-actions {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
            gap: 1.5rem;
            margin-bottom: 2rem;
        }

        .quick-action-card {
            background: linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%);
            color: var(--text-primary);
            padding: 1.5rem;
            border-radius: var(--radius-lg);
            text-align: center;
            cursor: pointer;
            transition: all 0.3s ease;
            box-shadow: var(--shadow-md);
            border: 2px solid transparent;
            position: relative;
            overflow: hidden;
        }

        .quick-action-card::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0.05) 100%);
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .quick-action-card:hover {
            transform: translateY(-5px) scale(1.02);
            box-shadow: var(--shadow-xl);
            border-color: rgba(255,255,255,0.3);
        }

        .quick-action-card:hover::before {
            opacity: 1;
        }

        .quick-action-title {
            font-weight: 700;
            font-size: 1.1rem;
            margin-bottom: 0.5rem;
            position: relative;
            z-index: 1;
        }

        .quick-action-desc {
            font-size: 0.9rem;
            opacity: 0.8;
            position: relative;
            z-index: 1;
        }
        
        /* 轻量级Jupyter卡片特殊样式 */
        .quick-action-card.jupyter-light {
            background: linear-gradient(135deg, #10b981 0%, #059669 100%);
            border-color: rgba(16, 185, 129, 0.3);
        }
        
        .quick-action-card.jupyter-light:hover {
            background: linear-gradient(135deg, #059669 0%, #047857 100%);
            border-color: rgba(16, 185, 129, 0.5);
        }

        /* 快速操作卡片loading状态 */
        .quick-action-card.loading {
            pointer-events: none;
            opacity: 0.7;
            position: relative;
        }

        .quick-action-card.loading::after {
            content: '';
            position: absolute;
            top: 50%;
            left: 50%;
            width: 20px;
            height: 20px;
            margin: -10px 0 0 -10px;
            border: 2px solid transparent;
            border-top: 2px solid var(--primary-color);
            border-radius: 50%;
            animation: spin 1s linear infinite;
        }

        /* 响应式设计 */
        @media (max-width: 768px) {
            .container {
                padding: 10px;
            }
            
            .content-wrapper {
                padding: 1rem;
            }
            
            .header h1 {
                font-size: 2rem;
            }
            
            .stats {
                grid-template-columns: repeat(2, 1fr);
                gap: 1rem;
            }
            
            .quick-actions {
                grid-template-columns: 1fr;
            }
            
            .user-list {
                grid-template-columns: 1fr;
            }
            
            .button-group {
                flex-direction: column;
            }
            
            .button-group button {
                width: 100%;
            }
        }

        @media (max-width: 480px) {
            .stats {
                grid-template-columns: 1fr;
            }
            
            .stat-number {
                font-size: 2rem;
            }
        }

        /* 加载动画 */
        .loading {
            display: inline-block;
            width: 20px;
            height: 20px;
            border: 3px solid rgba(255,255,255,.3);
            border-radius: 50%;
            border-top-color: #fff;
            animation: spin 1s ease-in-out infinite;
        }

        @keyframes spin {
            to { transform: rotate(360deg); }
        }

        /* 滚动条样式 */
        ::-webkit-scrollbar {
            width: 8px;
        }

        ::-webkit-scrollbar-track {
            background: var(--bg-secondary);
            border-radius: var(--radius-sm);
        }

        ::-webkit-scrollbar-thumb {
            background: var(--border-color);
            border-radius: var(--radius-sm);
        }

        ::-webkit-scrollbar-thumb:hover {
            background: var(--border-hover);
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🚀 用户环境管理系统</h1>
            <p>高效管理用户开发环境，一键部署多种服务</p>
        </div>
        
        <div class="main-content">
            <div class="content-wrapper">
                <!-- 统计信息 -->
                <div class="stats" id="stats">
            <div class="stat-card">
                <div class="stat-number" id="totalUsers">0</div>
                <div class="stat-label">总用户数</div>
            </div>
            <div class="stat-card">
                <div class="stat-number" id="activeUsers">0</div>
                <div class="stat-label">活跃用户</div>
            </div>
            <div class="stat-card">
                <div class="stat-number" id="runningEnvironments">0</div>
                <div class="stat-label">运行中环境</div>
            </div>
            <div class="stat-card">
                <div class="stat-number" id="stoppedEnvironments">0</div>
                <div class="stat-label">停止环境</div>
            </div>
        </div>

        <!-- 快速操作 -->
        <div class="quick-actions">
            <!-- <div class="quick-action-card" onclick="showQuickCreate('IDE')">
                <div class="quick-action-title">🖥️ 快速创建IDE环境</div>
                <div class="quick-action-desc">适合代码开发和编程练习</div>
            </div>
            <div class="quick-action-card" onclick="showQuickCreate('JUPYTER')">
                <div class="quick-action-title">📊 快速创建Jupyter环境</div>
                <div class="quick-action-desc">适合数据分析和机器学习</div>
            </div> -->
            <!-- <div class="quick-action-card jupyter-light" onclick="showQuickCreate('JUPYTER_LIGHT')">
                <div class="quick-action-title">🚀 轻量级Jupyter环境</div>
                <div class="quick-action-desc">仅包含Jupyter Lab，资源占用更少</div>
            </div>
            <div class="quick-action-card" onclick="showQuickCreate('VIRTUAL_DESKTOP')">
                <div class="quick-action-title">🖥️ 快速创建虚拟桌面环境</div>
                <div class="quick-action-desc">适合图形界面开发和远程桌面</div>
            </div>
            <div class="quick-action-card" onclick="showQuickCreate('REDIS')">
                <div class="quick-action-title">🔴 快速创建Redis环境</div>
                <div class="quick-action-desc">缓存和会话存储服务</div>
            </div>
            <div class="quick-action-card" onclick="showQuickCreate('MYSQL')">
                <div class="quick-action-title">🗄️ 快速创建MySQL环境</div>
                <div class="quick-action-desc">关系型数据库服务</div>
            </div>
            <div class="quick-action-card" onclick="showQuickCreate('RABBITMQ')">
                <div class="quick-action-title">🐰 快速创建RabbitMQ环境</div>
                <div class="quick-action-desc">消息队列服务</div>
            </div>
            <div class="quick-action-card" onclick="showQuickCreate('ELASTICSEARCH')">
                <div class="quick-action-title">🔍 快速创建Elasticsearch环境</div>
                <div class="quick-action-desc">搜索引擎和数据分析</div>
            </div>
            <div class="quick-action-card" onclick="showQuickCreate('FULL_STACK')">
                <div class="quick-action-title">🏗️ 快速创建全栈环境</div>
                <div class="quick-action-desc">包含所有服务的完整开发环境</div>
            </div> -->
            <div class="quick-action-card" onclick="openMonacoEditor()">
                <div class="quick-action-title">📝 Monaco Editor 演示</div>
                <div class="quick-action-desc">代码编辑器功能演示和代码执行测试</div>
            </div>
        </div>

        <!-- 创建用户 -->
        <div class="collapsible-section">
            <div class="collapsible-header" onclick="toggleCollapsible('createUserSection')">
                <h2>👤 创建新用户</h2>
                <span class="collapsible-toggle" id="createUserToggle">▼</span>
            </div>
            <div class="collapsible-content" id="createUserSection">
                <!-- 快速创建用户 -->
                <div class="form-group">
                    <h3>🚀 快速创建用户（随机值）</h3>
                    <div class="form-group">
                        <label for="quickRole">角色:</label>
                        <select id="quickRole" name="quickRole">
                            <option value="student">学生</option>
                            <option value="teacher">教师</option>
                            <option value="admin">管理员</option>
                        </select>
                    </div>
                    <div class="form-group">
                        <label for="batchCount">批量创建数量:</label>
                        <input type="number" id="batchCount" name="batchCount" value="1" min="1" max="10">
                    </div>
                    <div class="button-group">
                        <button onclick="createRandomUser()" class="btn-success">创建单个随机用户</button>
                        <button onclick="createRandomUsersBatch()" class="btn-info">批量创建随机用户</button>
                    </div>
                </div>
                
                <hr style="margin: 1.5rem 0; border: none; height: 1px; background: linear-gradient(90deg, transparent, var(--border-color), transparent);">
                
                <!-- 手动创建用户 -->
                <div class="form-group">
                    <h3>✏️ 手动创建用户</h3>
                    <form id="createUserForm">
                        <div class="form-group">
                            <label for="userId">用户ID:</label>
                            <input type="text" id="userId" name="userId" required>
                        </div>
                        <div class="form-group">
                            <label for="username">用户名:</label>
                            <input type="text" id="username" name="username" required>
                        </div>
                        <div class="form-group">
                            <label for="email">邮箱:</label>
                            <input type="email" id="email" name="email" required>
                        </div>
                        <div class="form-group">
                            <label for="role">角色:</label>
                            <select id="role" name="role" required>
                                <option value="student">学生</option>
                                <option value="teacher">教师</option>
                                <option value="admin">管理员</option>
                            </select>
                        </div>
                        <button type="submit" class="btn-primary">创建用户</button>
                    </form>
                </div>
            </div>
        </div>

        <!-- 共享IDE管理 -->
        <div class="collapsible-section">
            <div class="collapsible-header" onclick="toggleCollapsible('sharedIdeSection')">
                <h2>👥 共享IDE管理（单容器多进程，按班级）</h2>
                <span class="collapsible-toggle" id="sharedIdeToggle">▼</span>
            </div>
            <div class="collapsible-content" id="sharedIdeSection">
                <div class="form-group">
                    <label for="sharedGroupId">班级/分组ID:</label>
                    <input type="text" id="sharedGroupId" placeholder="如 class001">
                </div>
                <div class="form-group">
                    <label for="sharedStudentIds">学生ID列表（逗号分隔或逐行）：</label>
                    <textarea id="sharedStudentIds" rows="4" placeholder="stu01,stu02,stu03"></textarea>
                </div>
                <div class="button-group">
                    <button onclick="createSharedIde()" class="btn-success">创建共享IDE</button>
                    <button onclick="deleteSharedIde()" class="btn-danger">删除共享IDE</button>
                    <button onclick="generateNginx()" class="btn-info">生成Nginx反代配置</button>
                    <button onclick="createSharedJupyterHub()" class="btn-primary">创建共享JupyterHub</button>
                    <button onclick="deleteSharedJupyterHub()" class="btn-danger">删除共享JupyterHub</button>
                    <button onclick="createSharedMySQL()" class="btn-primary">创建共享MySQL</button>
                    <button onclick="deleteSharedMySQL()" class="btn-danger">删除共享MySQL</button>
                </div>
                <div id="sharedResult" style="margin-top:12px;"></div>
                
                <!-- 现有共享IDE环境列表 -->
                <div id="sharedIDEEnvironmentsList" style="margin-top:20px;"></div>
            </div>
        </div>

        <!-- 用户环境管理 -->
        <div class="collapsible-section">
            <div class="collapsible-header" onclick="toggleCollapsible('userEnvironmentSection')">
                <h2>🔧 用户环境管理</h2>
                <span class="collapsible-toggle" id="userEnvironmentToggle">▼</span>
            </div>
            <div class="collapsible-content" id="userEnvironmentSection">
                <div class="form-group">
                    <label for="envUserId">用户ID:</label>
                    <input type="text" id="envUserId" name="envUserId">
                </div>
                <div class="form-group">
                    <label for="envRole">角色:</label>
                    <select id="envRole" name="envRole">
                        <option value="student">学生</option>
                        <option value="teacher">教师</option>
                        <option value="admin">管理员</option>
                    </select>
                </div>
                <div class="form-group">
                    <label for="envType">环境类型:</label>
                    <select id="envType" name="envType">
                        <option value="IDE">仅IDE环境</option>
                        <option value="JUPYTER">仅Jupyter环境</option>
<!--                        <option value="JUPYTER_LIGHT">轻量级Jupyter环境</option>-->
                        <option value="VIRTUAL_DESKTOP">仅虚拟桌面环境</option>
                        <option value="REDIS">仅Redis环境</option>
                        <option value="MYSQL">仅MySQL环境</option>
                        <option value="RABBITMQ">仅RabbitMQ环境</option>
                        <option value="ELASTICSEARCH">仅Elasticsearch环境</option>
<!--                        <option value="FULL_STACK">全栈环境 (所有服务)</option>-->
                    </select>
                </div>
                <div class="button-group">
                    <button onclick="createEnvironment()" class="btn-success">创建环境</button>
                    <button onclick="createSelectiveEnvironment()" class="btn-info">选择性创建</button>
                    <button onclick="startEnvironment()" class="btn-success">启动环境</button>
                    <button onclick="stopEnvironment()" class="btn-warning">停止环境</button>
                    <button onclick="deleteEnvironment()" class="btn-danger">删除环境</button>
                </div>
                
                <!-- 环境创建进度显示 -->
                <div id="environmentProgress" style="display: none; margin-top: 15px;">
                    <div style="background: var(--bg-secondary); padding: 15px; border-radius: var(--radius-md); border-left: 4px solid var(--primary-color);">
                        <div style="font-weight: bold; margin-bottom: 10px;">🚀 环境创建进度</div>
                        <div id="environmentStatus">准备创建...</div>
                        <div id="environmentDetails" style="font-size: 0.9em; color: var(--text-muted); margin-top: 8px;"></div>
                        <div id="environmentProgressBar" style="margin-top: 10px; display: none;">
                            <div class="progress-container">
                                <div class="progress-bar">
                                    <div class="progress-fill" id="progressFill"></div>
                                </div>
                                <div class="progress-text" id="progressText">0%</div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- 文件上传管理 -->
        <div class="collapsible-section">
            <div class="collapsible-header" onclick="toggleCollapsible('fileUploadSection')">
                <h2>📁 文件上传到IDE</h2>
                <span class="collapsible-toggle" id="fileUploadToggle">▼</span>
            </div>
            <div class="collapsible-content" id="fileUploadSection">
                <div class="form-group">
                    <label for="uploadUserId">用户ID:</label>
                    <input type="text" id="uploadUserId" name="uploadUserId" placeholder="输入要上传文件的用户ID">
                </div>
                <div class="form-group">
                    <label for="uploadTargetDir">目标目录:</label>
                    <input type="text" id="uploadTargetDir" name="uploadTargetDir" value="/home/coder/project" placeholder="容器内的目标目录路径">
                </div>
                
                <!-- 单文件上传 -->
                <div class="form-group">
                    <label for="singleFile">选择单个文件:</label>
                    <input type="file" id="singleFile" name="singleFile" accept="*/*">
                    <button onclick="uploadSingleFile()" class="btn-success" style="margin-top: 10px;">上传单个文件</button>
                </div>
                
                <!-- 批量文件上传 -->
                <div class="form-group">
                    <label for="multipleFiles">选择多个文件:</label>
                    <input type="file" id="multipleFiles" name="multipleFiles" multiple accept="*/*">
                    <button onclick="uploadMultipleFiles()" class="btn-success" style="margin-top: 10px;">批量上传文件</button>
                </div>
                
                <!-- 权限修复按钮 -->
                <div class="form-group" style="margin-top: 20px; padding-top: 15px; border-top: 1px solid var(--border-color);">
                    <label>🔧 权限修复工具:</label>
                    <button onclick="fixUserPermissions()" class="btn-warning" style="margin-top: 10px;">修复IDE权限问题</button>
                    <div style="font-size: 0.9em; color: var(--text-muted); margin-top: 5px;">
                        💡 如果遇到"权限被拒绝"错误，请点击此按钮修复IDE容器权限
                    </div>
                </div>
                
                <!-- 上传进度显示 -->
                <div id="uploadProgress" style="display: none; margin-top: 15px;">
                    <div style="background: var(--bg-secondary); padding: 15px; border-radius: var(--radius-md); border-left: 4px solid var(--primary-color);">
                        <div style="font-weight: bold; margin-bottom: 10px;">📤 上传进度</div>
                        <div id="uploadStatus">准备上传...</div>
                        <div id="uploadDetails" style="font-size: 0.9em; color: var(--text-muted); margin-top: 8px;"></div>
                        <div id="uploadProgressBar" style="margin-top: 10px; display: none;">
                            <div class="progress-container">
                                <div class="progress-bar">
                                    <div class="progress-fill" id="uploadProgressFill"></div>
                                </div>
                                <div class="progress-text" id="uploadProgressText">0%</div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- 文件树管理 -->
        <div class="collapsible-section">
            <div class="collapsible-header" onclick="toggleCollapsible('fileTreeSection')">
                <h2>🌳 IDE文件树</h2>
                <span class="collapsible-toggle" id="fileTreeToggle">▼</span>
            </div>
            <div class="collapsible-content" id="fileTreeSection">
                <div class="form-group">
                    <label for="treeUserId">用户ID:</label>
                    <input type="text" id="treeUserId" name="treeUserId" placeholder="输入要查看文件的用户ID">
                </div>
                <div class="form-group">
                    <label for="treeRootDir">根目录:</label>
                    <input type="text" id="treeRootDir" name="treeRootDir" value="/home/coder/project" placeholder="要查看的根目录路径">
                </div>
                <div class="form-group">
                    <button onclick="loadFileTree()" class="btn-success">加载文件树</button>
                    <button onclick="refreshFileTree()" class="btn-warning" style="margin-left: 10px;">刷新文件树</button>
                </div>
                
                <!-- 文件树显示区域 -->
                <div id="fileTreeContainer" class="file-tree-container" style="display: none;">
                    <div id="fileTreeContent"></div>
                </div>
                
                <!-- 文件树加载状态 -->
                <div id="fileTreeLoading" class="file-tree-loading" style="display: none;">
                    <div style="text-align: center; padding: 20px; color: var(--text-muted);">
                        <div class="loading"></div>
                        <div style="margin-top: 10px;">正在加载文件树...</div>
                    </div>
                </div>
                
                <!-- 文件树错误信息 -->
                <div id="fileTreeError" class="file-tree-error" style="display: none;"></div>
            </div>
        </div>

                <!-- 用户列表 -->
                <div class="collapsible-section">
                    <div class="collapsible-header" onclick="toggleCollapsible('userListSection')">
                        <h2>📋 用户列表</h2>
                        <span class="collapsible-toggle" id="userListToggle">▼</span>
                    </div>
                    <div class="collapsible-content" id="userListSection">
                        <button onclick="loadUsers()" class="btn-success">刷新用户列表</button>
                        <div id="userList" class="user-list"></div>
                    </div>
                </div>

        <!-- 环境类型选择模态对话框 -->
        <div id="environmentTypeModal" class="modal" style="display: none;">
            <div class="modal-content">
                <div class="modal-header">
                    <h3>选择环境类型</h3>
                    <span class="close" onclick="closeEnvironmentTypeModal()">&times;</span>
                </div>
                <div class="modal-body">
                    <p>为用户 <span id="modalUserId"></span> 选择要创建的环境类型：</p>
                    <div class="form-group">
                        <label for="modalEnvType">环境类型:</label>
                        <select id="modalEnvType" class="form-control">
                            <option value="IDE">IDE - 仅IDE环境</option>
                            <option value="JUPYTER">JUPYTER - 仅Jupyter环境</option>
<!--                            <option value="JUPYTER_LIGHT">JUPYTER_LIGHT - 轻量级Jupyter环境</option>-->
                            <option value="VIRTUAL_DESKTOP">VIRTUAL_DESKTOP - 仅虚拟桌面环境</option>
                            <option value="REDIS">REDIS - 仅Redis环境</option>
                            <option value="MYSQL">MYSQL - 仅MySQL环境</option>
                            <option value="RABBITMQ">RABBITMQ - 仅RabbitMQ环境</option>
                            <option value="ELASTICSEARCH">ELASTICSEARCH - 仅Elasticsearch环境</option>
<!--                            <option value="FULL_STACK">FULL_STACK - 全栈环境 (所有服务)</option>-->
                        </select>
                    </div>
                </div>
                <div class="modal-footer">
                    <button onclick="confirmEnvironmentType()" class="btn-success">确认创建</button>
                    <button onclick="closeEnvironmentTypeModal()" class="btn-secondary">取消</button>
                </div>
            </div>
        </div>

        <!-- 使用说明 -->
                <div class="collapsible-section">
                    <div class="collapsible-header" onclick="toggleCollapsible('helpSection')">
                        <h2>📖 功能说明</h2>
                        <span class="collapsible-toggle" id="helpToggle">▼</span>
                    </div>
                    <div class="collapsible-content" id="helpSection">
                        <div style="background: var(--bg-secondary); padding: 1.5rem; border-radius: var(--radius-md); border-left: 4px solid var(--primary-color);">
                            <h4 style="margin-top: 0; color: var(--text-primary);">🎯 环境类型说明：</h4>
                            <ul style="color: var(--text-secondary);">
                                <li><strong>🖥️ IDE环境</strong>：仅包含Code Server在线IDE，适合代码开发和编程练习</li>
                                <li><strong>📊 Jupyter环境</strong>：仅包含Jupyter Lab，适合数据分析和机器学习</li>
                                <li><strong>🖥️ 虚拟桌面环境</strong>：仅包含Ubuntu桌面环境，适合图形界面开发和远程桌面</li>
                                <li><strong>🔴 Redis环境</strong>：仅包含Redis缓存服务，适合缓存和会话存储</li>
                                <li><strong>🗄️ MySQL环境</strong>：仅包含MySQL数据库服务，适合关系型数据存储</li>
                                <li><strong>🐰 RabbitMQ环境</strong>：仅包含RabbitMQ消息队列服务，适合异步消息处理</li>
                                <li><strong>🔍 Elasticsearch环境</strong>：仅包含Elasticsearch搜索引擎，适合数据搜索和分析</li>

                                <li><strong>🏗️ 全栈环境</strong>：包含所有服务（IDE、Jupyter、Redis、MySQL、RabbitMQ、Elasticsearch）</li>
                            </ul>
                            
                            <h4 style="color: var(--text-primary);">💡 使用技巧：</h4>
                            <ul style="color: var(--text-secondary);">
                                <li>点击顶部快速操作卡片可以快速选择环境类型</li>
                                <li>用户卡片中的"快速创建"按钮可以为特定用户创建环境</li>
                                <li>环境类型标签用不同颜色区分：IDE（蓝色）、Jupyter（橙色）、全栈（绿色）</li>
                                <li>选择性创建可以节省系统资源，提高部署效率</li>
                            </ul>
                            
                            <h4 style="color: var(--text-primary);">🔧 操作说明：</h4>
                            <ul style="color: var(--text-secondary);">
                                <li><strong>创建环境</strong>：使用默认API创建环境，支持环境类型参数</li>
                                <li><strong>选择性创建</strong>：使用专用API创建指定类型的环境</li>
                                <li><strong>快速创建</strong>：为用户列表中的特定用户快速创建环境</li>
                                <li><strong>文件上传</strong>：支持单文件和批量文件上传到IDE容器</li>
                                <li><strong>快速上传</strong>：在用户卡片中点击"上传文件"按钮快速上传</li>
                            </ul>
                            
                            <h4 style="color: var(--text-primary);">📁 文件上传功能：</h4>
                            <ul style="color: var(--text-secondary);">
                                <li><strong>单文件上传</strong>：选择单个文件上传到指定用户的IDE容器</li>
                                <li><strong>批量上传</strong>：选择多个文件同时上传，提高效率</li>
                                <li><strong>目标目录</strong>：可自定义上传到容器内的目标目录路径</li>
                                <li><strong>进度显示</strong>：实时显示上传进度和状态信息</li>
                                <li><strong>文件类型</strong>：支持所有文件类型，无限制</li>
                                <li><strong>安全处理</strong>：自动清理文件名中的特殊字符，确保安全</li>
                            </ul>
                        </div>
        </div>

                <!-- 消息显示区域 -->
                <div id="messageArea"></div>
            </div>
        </div>
    </div>

    <script>
        const API_BASE = '/api/users';
        const OP_ROLE = 'admin';
        
        // 可折叠区域切换函数
        function toggleCollapsible(sectionId) {
            const content = document.getElementById(sectionId);
            const toggle = document.getElementById(sectionId.replace('Section', 'Toggle'));
            
            if (content.classList.contains('collapsed')) {
                content.classList.remove('collapsed');
                toggle.classList.remove('rotated');
                toggle.textContent = '▼';
            } else {
                content.classList.add('collapsed');
                toggle.classList.add('rotated');
                toggle.textContent = '▲';
            }
        }
        
        // 页面加载时获取统计信息
        document.addEventListener('DOMContentLoaded', function() {
            // 显示页面加载进度
            showEnvironmentProgress(true, '正在加载页面数据...', '正在获取统计信息和用户列表，请稍候...', false);
            
            // 延迟执行，让用户看到加载提示
            setTimeout(async () => {
                try {
                    await loadStats();
                    await loadUsers();
                    await loadSharedIDEEnvironments();
                    
                    // 显示加载完成状态
                    showEnvironmentProgress(true, '✅ 页面加载完成！', '统计信息和用户列表已加载完成', false);
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showEnvironmentProgress(false);
                    }, 3000);
                } catch (error) {
                    // 显示错误状态
                    showEnvironmentProgress(true, '❌ 页面加载失败！', error.message, false);
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showEnvironmentProgress(false);
                    }, 3000);
                }
            }, 800);
            
            // 页面加载完成后，将所有折叠区域设置为默认折叠状态
            setTimeout(() => {
                const collapsibleSections = [
                    'createUserSection',
                    'userEnvironmentSection', 
                    'fileUploadSection',
                    'fileTreeSection',
                    'userListSection',
                    'helpSection'
                ];
                
                collapsibleSections.forEach(sectionId => {
                    const content = document.getElementById(sectionId);
                    const toggle = document.getElementById(sectionId.replace('Section', 'Toggle'));
                    
                    if (content && toggle) {
                        content.classList.add('collapsed');
                        toggle.classList.add('rotated');
                        toggle.textContent = '▲';
                    }
                });

                // 确保共享IDE管理默认展开
                const shared = document.getElementById('sharedIdeSection');
                const sharedToggle = document.getElementById('sharedIdeToggle');
                if (shared && sharedToggle) {
                    shared.classList.remove('collapsed');
                    sharedToggle.classList.remove('rotated');
                    sharedToggle.textContent = '▼';
                }
            }, 1000); // 延迟1秒执行，确保DOM完全加载
        });

        // 创建用户表单提交
        document.getElementById('createUserForm').addEventListener('submit', function(e) {
            e.preventDefault();
            createUser();
        });

        // 创建用户
        async function createUser() {
            const formData = new FormData(document.getElementById('createUserForm'));
            const user = {
                userId: formData.get('userId'),
                username: formData.get('username'),
                email: formData.get('email'),
                role: formData.get('role')
            };

            try {
                const response = await fetch(API_BASE, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(user)
                });

                if (response.ok) {
                    showMessage('用户创建成功！', 'success');
                    document.getElementById('createUserForm').reset();
                    loadUsers();
                    loadStats();
                } else {
                    showMessage('用户创建失败！', 'error');
                }
            } catch (error) {
                showMessage('创建用户时发生错误: ' + error.message, 'error');
            }
        }

        // 创建随机用户
        async function createRandomUser() {
            const role = document.getElementById('quickRole').value;
            
            try {
                const response = await fetch(`${API_BASE}/random?role=${role}`, {
                    method: 'POST'
                });

                if (response.ok) {
                    const user = await response.json();
                    showMessage(`随机用户创建成功！用户ID: ${user.userId}, 用户名: ${user.username}, 邮箱: ${user.email}, 密码: ${user.password}`, 'success');
                    loadUsers();
                    loadStats();
                } else {
                    showMessage('随机用户创建失败！', 'error');
                }
            } catch (error) {
                showMessage('创建随机用户时发生错误: ' + error.message, 'error');
            }
        }

        // 批量创建随机用户
        async function createRandomUsersBatch() {
            const role = document.getElementById('quickRole').value;
            const count = parseInt(document.getElementById('batchCount').value) || 1;
            
            if (count < 1 || count > 10) {
                showMessage('批量创建数量必须在1-10之间', 'error');
                return;
            }
            
            try {
                const response = await fetch(`${API_BASE}/random/batch?count=${count}&role=${role}`, {
                    method: 'POST'
                });

                if (response.ok) {
                    const result = await response.json();
                    let message = `批量创建成功！创建了 ${result.users.length} 个用户。\n`;
                    result.users.forEach((user, index) => {
                        message += `\n用户${index + 1}:\n`;
                        message += `  用户ID: ${user.userId}\n`;
                        message += `  用户名: ${user.username}\n`;
                        message += `  邮箱: ${user.email}\n`;
                        message += `  密码: ${user.password}\n`;
                    });
                    showMessage(message, 'success');
                    loadUsers();
                    loadStats();
                } else {
                    showMessage('批量创建随机用户失败！', 'error');
                }
            } catch (error) {
                showMessage('批量创建随机用户时发生错误: ' + error.message, 'error');
            }
        }

        // 创建环境（默认完整环境）
        async function createEnvironment() {
            const userId = document.getElementById('envUserId').value;
            const role = document.getElementById('envRole').value;
            const envType = document.getElementById('envType').value;

            if (!userId) {
                showMessage('请输入用户ID', 'error');
                return;
            }

            // 显示创建进度
            showEnvironmentProgress(true, '正在创建环境...', `正在为用户 ${userId} 创建 ${getEnvironmentTypeText(envType)} 环境，请稍候...`, true);
            
            // 启动进度模拟
            const progressInterval = simulateEnvironmentProgress();

            try {
                const response = await fetch(`${API_BASE}/${userId}/environment?userRole=${role}&environmentTypes=${envType}`, {
                    method: 'POST'
                });

                // 停止进度模拟
                clearInterval(progressInterval);
                updateEnvironmentProgress(100);

                if (response.ok) {
                    const environment = await response.json();
                    let message = `环境创建成功！`;
                    if (environment.ideUrl) message += ` IDE地址: ${environment.ideUrl}`;
                    if (environment.jupyterUrl) message += ` Jupyter地址: ${environment.jupyterUrl}`;
                    
                    // 显示成功状态
                    showEnvironmentProgress(true, '✅ 环境创建成功！', message, false);
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showEnvironmentProgress(false);
                    }, 3000);
                    
                    showMessage(message, 'success');
                    loadUsers();
                    loadStats();
                } else {
                    // 显示失败状态
                    showEnvironmentProgress(true, '❌ 环境创建失败！', '请检查用户ID和权限设置', false);
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showEnvironmentProgress(false);
                    }, 3000);
                    
                    showMessage('环境创建失败！', 'error');
                }
            } catch (error) {
                // 停止进度模拟
                clearInterval(progressInterval);
                
                // 显示错误状态
                showEnvironmentProgress(true, '❌ 创建环境时发生错误', error.message, false);
                
                // 3秒后隐藏进度显示
                setTimeout(() => {
                    showEnvironmentProgress(false);
                }, 3000);
                
                showMessage('创建环境时发生错误: ' + error.message, 'error');
            }
        }

        // 共享IDE：创建
        async function createSharedIde() {
            const groupId = document.getElementById('sharedGroupId').value.trim();
            const raw = document.getElementById('sharedStudentIds').value.trim();
            if (!groupId || !raw) { showMessage('请填写groupId与学生ID列表', 'error'); return; }
            const studentIds = raw.split(/[\n,]+/).map(s=>s.trim()).filter(Boolean);
            try {
                const resp = await fetch(`${API_BASE}/shared/environment/ide`, {
                    method: 'POST', headers: {'Content-Type':'application/json'},
                    body: JSON.stringify({ groupId, studentIds, operatorRole: OP_ROLE })
                });
                const data = await resp.json();
                if (!resp.ok || !data.success) throw new Error(data.message || '创建失败');
                renderSharedResult(groupId, data);
                showMessage('共享IDE创建成功', 'success');
            } catch (e) { showMessage('创建共享IDE失败: ' + e.message, 'error'); }
        }

        // 共享IDE：删除
        async function deleteSharedIde() {
            const groupId = document.getElementById('sharedGroupId').value.trim();
            if (!groupId) { showMessage('请填写groupId', 'error'); return; }
            if (!confirm('确定删除共享IDE?')) return;
            try {
                const resp = await fetch(`${API_BASE}/shared/environment?groupId=${encodeURIComponent(groupId)}&operatorRole=${OP_ROLE}`, { method:'DELETE' });
                const data = await resp.json();
                if (!resp.ok || !data.success) throw new Error(data.message || '删除失败');
                document.getElementById('sharedResult').innerHTML = '';
                showMessage('共享环境删除成功', 'success');
            } catch (e) { showMessage('删除共享环境失败: ' + e.message, 'error'); }
        }

        // 共享IDE：生成Nginx配置
        async function generateNginx() {
            const groupId = document.getElementById('sharedGroupId').value.trim();
            if (!groupId) { showMessage('请填写groupId', 'error'); return; }
            const serverName = prompt('输入服务器域名（如 ide.example.com ）', 'ide.example.com');
            if (!serverName) return;
            const basePath = prompt('输入基础路径（默认 /ide ）', '/ide') || '/ide';
            try {
                const resp = await fetch(`${API_BASE}/shared/environment/ide/nginx?groupId=${encodeURIComponent(groupId)}&serverName=${encodeURIComponent(serverName)}&basePath=${encodeURIComponent(basePath)}&operatorRole=${OP_ROLE}`);
                const text = await resp.text();
                if (!resp.ok) throw new Error(text);
                const pre = document.createElement('pre');
                pre.style.whiteSpace = 'pre-wrap';
                pre.textContent = text;
                const box = document.getElementById('sharedResult');
                box.innerHTML = '<h3>Nginx 配置</h3>';
                const copyBtn = document.createElement('button');
                copyBtn.className = 'btn-secondary';
                copyBtn.style.marginBottom = '8px';
                copyBtn.textContent = '复制配置';
                copyBtn.onclick = () => {
                    navigator.clipboard.writeText(pre.textContent).then(()=>showMessage('已复制Nginx配置','success')).catch(()=>showMessage('复制失败','error'));
                };
                box.appendChild(copyBtn);

                // 建议保存路径与部署命令
                const fileName = `nginx-shared-${groupId}.conf`;
                const savePath = `/etc/nginx/conf.d/${fileName}`;
                const genCmd = `./scripts/generate-nginx-config.sh ${groupId} ${serverName} ${basePath} http://localhost:8080 ./${fileName}`;
                const depCmd = `sudo ./scripts/deploy-nginx-config.sh ./${fileName} /etc/nginx/conf.d`;

                const info = document.createElement('div');
                info.style.margin = '8px 0';
                info.innerHTML = `
                    <div style="margin:6px 0;">建议保存到: <code>${savePath}</code>
                        <button class="btn-secondary" style="margin-left:6px;" onclick="navigator.clipboard.writeText('${savePath}').then(()=>showMessage('已复制路径','success'))">复制路径</button>
                    </div>
                    <div style="margin:6px 0;">生成命令:
                        <pre style="display:inline-block;margin:0 6px;">${genCmd}</pre>
                        <button class="btn-secondary" onclick="navigator.clipboard.writeText('${genCmd}').then(()=>showMessage('已复制命令','success'))">复制</button>
                    </div>
                    <div style="margin:6px 0;">部署命令:
                        <pre style="display:inline-block;margin:0 6px;">${depCmd}</pre>
                        <button class="btn-secondary" onclick="navigator.clipboard.writeText('${depCmd}').then(()=>showMessage('已复制命令','success'))">复制</button>
                    </div>
                `;
                box.appendChild(info);
                box.appendChild(pre);
                showMessage('Nginx配置已生成', 'success');
            } catch (e) { showMessage('生成Nginx配置失败: ' + e.message, 'error'); }
        }

        // 共享JupyterHub：创建
        async function createSharedJupyterHub() {
            const groupId = document.getElementById('sharedGroupId').value.trim();
            const raw = document.getElementById('sharedStudentIds').value.trim();
            if (!groupId || !raw) { showMessage('请填写groupId与学生ID列表', 'error'); return; }
            const studentIds = raw.split(/[\n,]+/).map(s=>s.trim()).filter(Boolean);
            try {
                const resp = await fetch(`${API_BASE}/shared/environment/jupyterhub`, {
                    method: 'POST', headers: {'Content-Type':'application/json'},
                    body: JSON.stringify({ groupId, studentIds, operatorRole: OP_ROLE })
                });
                const data = await resp.json();
                if (!resp.ok || !data.success) throw new Error(data.message || '创建失败');
                renderJupyterHubResult(groupId, data);
                showMessage('共享JupyterHub创建请求已提交', 'success');
            } catch (e) { showMessage('创建共享JupyterHub失败: ' + e.message, 'error'); }
        }

        // 共享JupyterHub：删除
        async function deleteSharedJupyterHub() {
            const groupId = document.getElementById('sharedGroupId').value.trim();
            if (!groupId) { showMessage('请填写groupId', 'error'); return; }
            if (!confirm('确定删除共享JupyterHub?')) return;
            try {
                const resp = await fetch(`${API_BASE}/shared/environment?groupId=${encodeURIComponent(groupId)}&operatorRole=${OP_ROLE}`, { method:'DELETE' });
                const data = await resp.json();
                if (!resp.ok || !data.success) throw new Error(data.message || '删除失败');
                document.getElementById('sharedResult').innerHTML = '';
                showMessage('共享环境删除成功', 'success');
            } catch (e) { showMessage('删除共享环境失败: ' + e.message, 'error'); }
        }

        function renderJupyterHubResult(groupId, data) {
            const box = document.getElementById('sharedResult');
            const urls = data.loginUrls || {};
            const hubPort = data.hubPort || '-';
            let html = `<div style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:12px;">
                <div style="font-weight:700;margin-bottom:8px;">JupyterHub 组: ${groupId}</div>
                <div style="color:#64748b;font-size:12px;margin-bottom:8px;">Hub端口: ${hubPort}</div>
                <table style="width:100%;border-collapse:collapse;font-size:14px;">
                <thead><tr><th style="text-align:left;border-bottom:1px solid #e2e8f0;padding:6px;">学生ID</th><th style="text-align:left;border-bottom:1px solid #e2e8f0;padding:6px;">登录入口</th><th style="padding:6px;"></th></tr></thead><tbody>`;
            Object.keys(urls).forEach(sid => {
                const url = urls[sid];
                html += `<tr>
                    <td style="padding:6px;border-bottom:1px solid #f1f5f9;">${sid}</td>
                    <td style="padding:6px;border-bottom:1px solid #f1f5f9;"><a href="${url}" target="_blank">${url}</a></td>
                    <td style="padding:6px;border-bottom:1px solid #f1f5f9;"><button class="btn-secondary" onclick="navigator.clipboard.writeText('${url}').then(()=>showMessage('已复制URL','success'))">复制</button></td>
                </tr>`;
            });
            html += '</tbody></table></div>';
            box.innerHTML = html;
        }

        function renderSharedResult(groupId, data) {
            const box = document.getElementById('sharedResult');
            const urls = data.studentUrls || {};
            const ports = data.ports || {};
            let html = `<div style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:12px;">
                <div style="font-weight:700;margin-bottom:8px;">共享组: ${groupId}</div>
                <table style="width:100%;border-collapse:collapse;font-size:14px;">
                <thead><tr><th style="text-align:left;border-bottom:1px solid #e2e8f0;padding:6px;">学生ID</th><th style="text-align:left;border-bottom:1px solid #e2e8f0;padding:6px;">端口</th><th style="text-align:left;border-bottom:1px solid #e2e8f0;padding:6px;">URL</th><th style="padding:6px;"></th></tr></thead><tbody>`;
            Object.keys(urls).forEach(sid => {
                const url = urls[sid];
                const port = ports[sid] || '-';
                html += `<tr>
                    <td style="padding:6px;border-bottom:1px solid #f1f5f9;">${sid}</td>
                    <td style="padding:6px;border-bottom:1px solid #f1f5f9;">${port}</td>
                    <td style="padding:6px;border-bottom:1px solid #f1f5f9;"><a href="${url}" target="_blank">${url}</a></td>
                    <td style="padding:6px;border-bottom:1px solid #f1f5f9;"><button class="btn-secondary" onclick="navigator.clipboard.writeText('${url}').then(()=>showMessage('已复制URL','success'))">复制</button></td>
                </tr>`;
            });
            html += '</tbody></table></div>';
            box.innerHTML = html;
        }

        // 共享MySQL：创建
        async function createSharedMySQL() {
            const groupId = document.getElementById('sharedGroupId').value.trim();
            const raw = document.getElementById('sharedStudentIds').value.trim();
            if (!groupId || !raw) { showMessage('请填写groupId与学生ID列表', 'error'); return; }
            const studentIds = raw.split(/[\n,]+/).map(s=>s.trim()).filter(Boolean);
            try {
                const resp = await fetch(`${API_BASE}/shared/environment/mysql`, {
                    method: 'POST', headers: {'Content-Type':'application/json'},
                    body: JSON.stringify({ groupId, studentIds, operatorRole: OP_ROLE })
                });
                const data = await resp.json();
                if (!resp.ok || !data.success) throw new Error(data.message || '创建失败');
                renderSharedMySQLResult(groupId, data);
                showMessage('共享MySQL创建成功', 'success');
            } catch (e) { showMessage('创建共享MySQL失败: ' + e.message, 'error'); }
        }

        // 共享MySQL：删除
        async function deleteSharedMySQL() {
            const groupId = document.getElementById('sharedGroupId').value.trim();
            if (!groupId) { showMessage('请填写groupId', 'error'); return; }
            if (!confirm('确定删除共享MySQL?')) return;
            try {
                const resp = await fetch(`${API_BASE}/shared/environment/mysql?groupId=${encodeURIComponent(groupId)}&operatorRole=${OP_ROLE}`, { method:'DELETE' });
                const data = await resp.json();
                if (!resp.ok || !data.success) throw new Error(data.message || '删除失败');
                document.getElementById('sharedResult').innerHTML = '';
                showMessage('共享MySQL删除成功', 'success');
            } catch (e) { showMessage('删除共享MySQL失败: ' + e.message, 'error'); }
        }

        function renderSharedMySQLResult(groupId, data) {
            const box = document.getElementById('sharedResult');
            const mysqlUrl = data.mysqlUrl || '-';
            const mysqlPort = data.mysqlPort || '-';
            const userDbInfo = data.userDbInfo || {};
            let html = `<div style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:12px;">
                <div style=\"font-weight:700;margin-bottom:8px;\">共享 MySQL 组: ${groupId}</div>
                <div style=\"color:#64748b;font-size:12px;margin-bottom:8px;\">地址: <a href=\"${mysqlUrl}\" target=\"_blank\">${mysqlUrl}</a> | 端口: ${mysqlPort}</div>
                <table style=\"width:100%;border-collapse:collapse;font-size:14px;\">
                <thead><tr>
                    <th style=\"text-align:left;border-bottom:1px solid #e2e8f0;padding:6px;\">学生ID</th>
                    <th style=\"text-align:left;border-bottom:1px solid #e2e8f0;padding:6px;\">数据库</th>
                    <th style=\"text-align:left;border-bottom:1px solid #e2e8f0;padding:6px;\">账号</th>
                    <th style=\"text-align:left;border-bottom:1px solid #e2e8f0;padding:6px;\">密码</th>
                    <th style=\"padding:6px;\"></th>
                </tr></thead><tbody>`;
            Object.keys(userDbInfo).forEach(sid => {
                const info = userDbInfo[sid] || {};
                const db = info.database || '-';
                const user = info.username || '-';
                const pass = info.password || '-';
                const jdbc = `jdbc:mysql://${mysqlUrl.replace(/^https?:\/\//,'')}/${db}?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true`;
                html += `<tr>
                    <td style=\"padding:6px;border-bottom:1px solid #f1f5f9;\">${sid}</td>
                    <td style=\"padding:6px;border-bottom:1px solid #f1f5f9;\">${db}</td>
                    <td style=\"padding:6px;border-bottom:1px solid #f1f5f9;\">${user}</td>
                    <td style=\"padding:6px;border-bottom:1px solid #f1f5f9;\">${pass}</td>
                    <td style=\"padding:6px;border-bottom:1px solid #f1f5f9;\">
                        <button class=\"btn-secondary\" onclick=\"navigator.clipboard.writeText('${jdbc}').then(()=>showMessage('已复制JDBC URL','success'))\">复制JDBC</button>
                    </td>
                </tr>`;
            });
            html += '</tbody></table></div>';
            box.innerHTML = html;
        }

        // 加载所有共享IDE环境
        async function loadSharedIDEEnvironments() {
            try {
                const response = await fetch(`${API_BASE}/shared/environment/ide`);
                if (response.ok) {
                    const environments = await response.json();
                    renderSharedIDEEnvironmentsList(environments);
                }
            } catch (error) {
                console.error('Failed to load shared IDE environments:', error);
            }
        }

        // 渲染共享IDE环境列表
        function renderSharedIDEEnvironmentsList(environments) {
            const container = document.getElementById('sharedIDEEnvironmentsList');
            if (!container) return;

            if (environments.length === 0) {
                container.innerHTML = '<p style="color: #64748b; text-align: center; padding: 20px;">暂无共享IDE环境</p>';
                return;
            }

            let html = '<h3>现有共享IDE环境</h3>';
            environments.forEach(env => {
                try {
                    const studentIds = JSON.parse(env.studentIds || '[]');
                    const portMapping = JSON.parse(env.portMapping || '{}');
                    const urlMapping = JSON.parse(env.urlMapping || '{}');
                    
                    html += `<div style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:12px;margin-bottom:12px;">
                        <div style="font-weight:700;margin-bottom:8px;">共享组: ${env.groupId} (${env.groupName || env.groupId})</div>
                        <div style="color:#64748b;font-size:12px;margin-bottom:8px;">状态: ${env.status} | 创建时间: ${env.createdAt}</div>
                        <table style="width:100%;border-collapse:collapse;font-size:14px;">
                        <thead><tr><th style="text-align:left;border-bottom:1px solid #e2e8f0;padding:6px;">学生ID</th><th style="text-align:left;border-bottom:1px solid #e2e8f0;padding:6px;">端口</th><th style="text-align:left;border-bottom:1px solid #e2e8f0;padding:6px;">URL</th><th style="padding:6px;"></th></tr></thead><tbody>`;
                    
                    studentIds.forEach(sid => {
                        const url = urlMapping[sid] || '-';
                        const port = portMapping[sid] || '-';
                        html += `<tr>
                            <td style="padding:6px;border-bottom:1px solid #f1f5f9;">${sid}</td>
                            <td style="padding:6px;border-bottom:1px solid #f1f5f9;">${port}</td>
                            <td style="padding:6px;border-bottom:1px solid #f1f5f9;"><a href="${url}" target="_blank">${url}</a></td>
                            <td style="padding:6px;border-bottom:1px solid #f1f5f9;"><button class="btn-secondary" onclick="navigator.clipboard.writeText('${url}').then(()=>showMessage('已复制URL','success'))">复制</button></td>
                        </tr>`;
                    });
                    
                    html += '</tbody></table>';
                    html += `<div style="margin-top:8px;">
                        <button class="btn-danger" onclick="deleteSharedIDEById('${env.groupId}')">删除此环境</button>
                        <button class="btn-secondary" onclick="generateNginxForExisting('${env.groupId}')">生成Nginx配置</button>
                    </div></div>`;
                } catch (e) {
                    console.error('Error parsing environment data:', e);
                }
            });
            
            container.innerHTML = html;
        }

        // 根据ID删除共享IDE环境
        async function deleteSharedIDEById(groupId) {
            if (!confirm(`确定删除共享IDE环境 ${groupId}?`)) return;
            try {
                const resp = await fetch(`${API_BASE}/shared/environment/ide?groupId=${encodeURIComponent(groupId)}&operatorRole=${OP_ROLE}`, { method:'DELETE' });
                const data = await resp.json();
                if (!resp.ok || !data.success) throw new Error(data.message || '删除失败');
                showMessage('共享IDE环境删除成功', 'success');
                await loadSharedIDEEnvironments(); // 重新加载列表
            } catch (e) { 
                showMessage('删除共享IDE环境失败: ' + e.message, 'error'); 
            }
        }

        // 为现有环境生成Nginx配置
        async function generateNginxForExisting(groupId) {
            const serverName = prompt('输入服务器域名（如 ide.example.com ）', 'ide.example.com');
            if (!serverName) return;
            const basePath = prompt('输入基础路径（默认 /ide ）', '/ide') || '/ide';
            try {
                const resp = await fetch(`${API_BASE}/shared/environment/ide/nginx?groupId=${encodeURIComponent(groupId)}&serverName=${encodeURIComponent(serverName)}&basePath=${encodeURIComponent(basePath)}&operatorRole=${OP_ROLE}`);
                const text = await resp.text();
                if (!resp.ok) throw new Error(text);
                
                // 显示配置
                const pre = document.createElement('pre');
                pre.style.whiteSpace = 'pre-wrap';
                pre.textContent = text;
                
                const dialog = document.createElement('div');
                dialog.style.cssText = 'position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.5);z-index:1000;display:flex;align-items:center;justify-content:center;';
                dialog.innerHTML = `<div style="background:white;padding:20px;border-radius:8px;max-width:90%;max-height:90%;overflow:auto;">
                    <h3>Nginx 配置 - ${groupId}</h3>
                    <button class="btn-secondary" style="margin-bottom:8px;" onclick="navigator.clipboard.writeText('${text}').then(()=>showMessage('已复制Nginx配置','success'))">复制配置</button>
                    <button class="btn-secondary" style="margin-left:8px;" onclick="this.closest('[style*=\"position:fixed\"]').remove()">关闭</button>
                    <pre style="background:#f8fafc;padding:12px;border-radius:4px;margin-top:8px;">${text}</pre>
                </div>`;
                
                document.body.appendChild(dialog);
                showMessage('Nginx配置已生成', 'success');
            } catch (e) { 
                showMessage('生成Nginx配置失败: ' + e.message, 'error'); 
            }
        }

        // 选择性创建环境
        async function createSelectiveEnvironment() {
            const userId = document.getElementById('envUserId').value;
            const role = document.getElementById('envRole').value;
            const envType = document.getElementById('envType').value;

            if (!userId) {
                showMessage('请输入用户ID', 'error');
                return;
            }

            // 显示创建进度
            showEnvironmentProgress(true, '正在选择性创建环境...', `正在为用户 ${userId} 创建 ${getEnvironmentTypeText(envType)} 环境，请稍候...`, true);
            
            // 启动进度模拟
            const progressInterval = simulateEnvironmentProgress();

            try {
                const response = await fetch(`${API_BASE}/${userId}/environment/selective?userRole=${role}&environmentTypes=${envType}`, {
                    method: 'POST'
                });

                // 停止进度模拟
                clearInterval(progressInterval);
                updateEnvironmentProgress(100);

                if (response.ok) {
                    const environment = await response.json();
                    let message = `选择性环境创建成功！类型: ${getEnvironmentTypeText(envType)}`;
                    if (environment.ideUrl) message += ` IDE地址: ${environment.ideUrl}`;
                    if (environment.jupyterUrl) message += ` Jupyter地址: ${environment.jupyterUrl}`;
                    
                    // 显示成功状态
                    showEnvironmentProgress(true, '✅ 选择性环境创建成功！', message, false);
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showEnvironmentProgress(false);
                    }, 3000);
                    
                    showMessage(message, 'success');
                    loadUsers();
                    loadStats();
                } else {
                    // 显示失败状态
                    showEnvironmentProgress(true, '❌ 选择性环境创建失败！', '请检查用户ID和权限设置', false);
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showEnvironmentProgress(false);
                    }, 3000);
                    
                    showMessage('选择性环境创建失败！', 'error');
                }
            } catch (error) {
                // 停止进度模拟
                clearInterval(progressInterval);
                
                // 显示错误状态
                showEnvironmentProgress(true, '❌ 创建选择性环境时发生错误', error.message, false);
                
                // 3秒后隐藏进度显示
                setTimeout(() => {
                    showEnvironmentProgress(false);
                }, 3000);
                
                showMessage('创建选择性环境时发生错误: ' + error.message, 'error');
            }
        }

        // 启动环境
        async function startEnvironment() {
            const userId = document.getElementById('envUserId').value;
            if (!userId) {
                showMessage('请输入用户ID', 'error');
                return;
            }

            // 显示启动进度
            showEnvironmentProgress(true, '正在启动环境...', `正在启动用户 ${userId} 的环境，请稍候...`, false);

            try {
                const response = await fetch(`${API_BASE}/${userId}/environment/start`, {
                    method: 'POST'
                });

                if (response.ok) {
                    const result = await response.json();
                    
                    if (result.success) {
                        // 显示成功状态
                        showEnvironmentProgress(true, '✅ 环境启动成功！', result.message, false);
                        loadUsers();
                    } else {
                        // 显示失败状态
                        showEnvironmentProgress(true, '❌ 环境启动失败！', result.message, false);
                    }
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showEnvironmentProgress(false);
                    }, 3000);
                    
                    showMessage(result.message, result.success ? 'success' : 'error');
                } else {
                    // 显示失败状态
                    showEnvironmentProgress(true, '❌ 环境启动失败！', '请检查用户ID和环境状态', false);
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showEnvironmentProgress(false);
                    }, 3000);
                    
                    showMessage('环境启动失败！', 'error');
                }
            } catch (error) {
                // 显示错误状态
                showEnvironmentProgress(true, '❌ 启动环境时发生错误', error.message, false);
                
                // 3秒后隐藏进度显示
                setTimeout(() => {
                    showEnvironmentProgress(false);
                }, 3000);
                
                showMessage('启动环境时发生错误: ' + error.message, 'error');
            }
        }

        // 停止环境
        async function stopEnvironment() {
            const userId = document.getElementById('envUserId').value;
            if (!userId) {
                showMessage('请输入用户ID', 'error');
                return;
            }

            // 显示停止进度
            showEnvironmentProgress(true, '正在停止环境...', `正在停止用户 ${userId} 的环境，请稍候...`, false);

            try {
                const response = await fetch(`${API_BASE}/${userId}/environment/stop`, {
                    method: 'POST'
                });

                if (response.ok) {
                    const result = await response.json();
                    
                    if (result.success) {
                        // 显示成功状态
                        showEnvironmentProgress(true, '✅ 环境停止成功！', result.message, false);
                        loadUsers();
                    } else {
                        // 显示失败状态
                        showEnvironmentProgress(true, '❌ 环境停止失败！', result.message, false);
                    }
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showEnvironmentProgress(false);
                    }, 3000);
                    
                    showMessage(result.message, result.success ? 'success' : 'error');
                } else {
                    // 显示失败状态
                    showEnvironmentProgress(true, '❌ 环境停止失败！', '请检查用户ID和环境状态', false);
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showEnvironmentProgress(false);
                    }, 3000);
                    
                    showMessage('环境停止失败！', 'error');
                }
            } catch (error) {
                // 显示错误状态
                showEnvironmentProgress(true, '❌ 停止环境时发生错误', error.message, false);
                
                // 3秒后隐藏进度显示
                setTimeout(() => {
                    showEnvironmentProgress(false);
                }, 3000);
                
                showMessage('停止环境时发生错误: ' + error.message, 'error');
            }
        }

        // 删除环境
        async function deleteEnvironment() {
            const userId = document.getElementById('envUserId').value;
            if (!userId) {
                showMessage('请输入用户ID', 'error');
                return;
            }

            if (!confirm('确定要删除该用户的环境吗？此操作不可恢复！')) {
                return;
            }

            // 显示删除进度
            showEnvironmentProgress(true, '正在删除环境...', `正在删除用户 ${userId} 的环境，请稍候...`, false);

            try {
                const response = await fetch(`${API_BASE}/${userId}/environment`, {
                    method: 'DELETE'
                });

                if (response.ok) {
                    const result = await response.json();
                    
                    if (result.success) {
                        // 显示成功状态
                        showEnvironmentProgress(true, '✅ 环境删除成功！', result.message, false);
                        loadUsers();
                        loadStats();
                    } else {
                        // 显示失败状态
                        showEnvironmentProgress(true, '❌ 环境删除失败！', result.message, false);
                    }
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showEnvironmentProgress(false);
                    }, 3000);
                    
                    showMessage(result.message, result.success ? 'success' : 'error');
                } else {
                    // 显示失败状态
                    showEnvironmentProgress(true, '❌ 环境删除失败！', '请检查用户ID和环境状态', false);
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showEnvironmentProgress(false);
                    }, 3000);
                    
                    showMessage('环境删除失败！', 'error');
                }
            } catch (error) {
                // 显示错误状态
                showEnvironmentProgress(true, '❌ 删除环境时发生错误', error.message, false);
                
                // 3秒后隐藏进度显示
                setTimeout(() => {
                    showEnvironmentProgress(false);
                }, 3000);
                
                showMessage('删除环境时发生错误: ' + error.message, 'error');
            }
        }

        // 加载用户列表
        async function loadUsers() {
            try {
                const response = await fetch(API_BASE);
                if (response.ok) {
                    const users = await response.json();
                    displayUsers(users);
                } else {
                    throw new Error('加载用户列表失败');
                }
            } catch (error) {
                showMessage('加载用户列表时发生错误: ' + error.message, 'error');
                throw error; // 重新抛出错误，让调用者处理
            }
        }

        // 显示用户列表
        async function displayUsers(users) {
            const userList = document.getElementById('userList');
            userList.innerHTML = '';

            for (const user of users) {
                const userCard = document.createElement('div');
                userCard.className = 'user-card';
                
                // 获取真实的环境状态
                const environmentInfo = await getUserEnvironmentInfo(user.userId);
                const statusClass = environmentInfo.status ? environmentInfo.status.toLowerCase() : 'stopped';
                const statusText = environmentInfo.status || '未创建';
                const envTypeDisplay = environmentInfo.environmentTypes ? 
                    environmentInfo.environmentTypes.map(type => `<span class="env-type ${type.toLowerCase()}">${getEnvironmentTypeText(type)}</span>`).join(' ') : '';

                userCard.innerHTML = `
                    <h3>${user.username} (${user.userId})</h3>
                    <p><strong>邮箱:</strong> ${user.email}</p>
                    <p><strong>角色:</strong> ${user.role}</p>
                    <p><strong>状态:</strong> <span class="status ${statusClass}">${statusText}</span> ${envTypeDisplay}</p>
                    ${environmentInfo.ideUrl ? `<p><strong>IDE:</strong> <a href="${environmentInfo.ideUrl}" target="_blank">${environmentInfo.ideUrl}</a></p>` : ''}
                    ${environmentInfo.jupyterUrl ? `<p><strong>Jupyter:</strong> <a href="${environmentInfo.jupyterUrl}" target="_blank">${environmentInfo.jupyterUrl}</a></p>` : ''}
                    ${environmentInfo.virtualDesktopUrl ? `<p><strong>虚拟桌面:</strong> <a href="${environmentInfo.virtualDesktopUrl}" target="_blank">${environmentInfo.virtualDesktopUrl}</a></p>` : ''}
                    ${environmentInfo.redisUrl ? `<p><strong>Redis:</strong> <a href="${environmentInfo.redisUrl}" target="_blank">${environmentInfo.redisUrl}</a></p>` : ''}
                    ${environmentInfo.mysqlUrl ? `${renderMySQLBlock(environmentInfo, user.userId)}` : ''}
                    ${environmentInfo.rabbitmqUrl ? `<p><strong>RabbitMQ:</strong> <a href="${environmentInfo.rabbitmqUrl}" target="_blank">${environmentInfo.rabbitmqUrl}</a></p>` : ''}
                    ${environmentInfo.elasticsearchUrl ? `<p><strong>Elasticsearch:</strong> <a href="${environmentInfo.elasticsearchUrl}" target="_blank">${environmentInfo.elasticsearchUrl}</a></p>` : ''}
                    <div class="button-group">
                        <button onclick="manageUser('${user.userId}', 'start')" class="btn-success">启动</button>
                        <button onclick="manageUser('${user.userId}', 'stop')" class="btn-warning">停止</button>
                        <button onclick="manageUser('${user.userId}', 'delete')" class="btn-danger">删除</button>
                        <button onclick="viewUserDetails('${user.userId}')" class="btn-success">详情</button>
                        <button onclick="quickCreateForUser('${user.userId}', '${user.role}')" class="btn-secondary">快速创建</button>
                        <button onclick="quickUploadForUser('${user.userId}')" class="btn-warning">上传文件</button>
                        <button onclick="quickViewFileTree('${user.userId}')" class="btn-info">查看文件</button>
                        <button onclick="openMonacoEditor('${user.userId}')" class="btn-primary">打开编辑器</button>
                    </div>
                `;
                
                userList.appendChild(userCard);
            }
        }

        // 获取用户环境信息
        async function getUserEnvironmentInfo(userId) {
            try {
                const response = await fetch(`${API_BASE}/${userId}/environment`);
                if (response.ok) {
                    return await response.json();
                } else {
                    return { status: null, environmentTypes: null };
                }
            } catch (error) {
                return { status: null, environmentTypes: null };
            }
        }

        // 获取环境类型文本
        function getEnvironmentTypeText(type) {
            switch (type) {
                case 'IDE': return 'IDE';
                case 'JUPYTER': return 'Jupyter';
                case 'JUPYTER_LIGHT': return '轻量级Jupyter';
                case 'VIRTUAL_DESKTOP': return '虚拟桌面';
                case 'REDIS': return 'Redis';
                case 'MYSQL': return 'MySQL';
                case 'RABBITMQ': return 'RabbitMQ';
                case 'ELASTICSEARCH': return 'Elasticsearch';
                case 'BOTH': return '完整';
                case 'FULL_STACK': return '全栈';
                default: return type;
            }
        }

        function renderMySQLBlock(env, userId) {
            const host = extractHost(env.mysqlUrl) || '-';
            const port = env.mysqlPort || extractPort(env.mysqlUrl) || '-';
            const account = `user_${userId}`;
            const password = env.mysqlPassword || `mysql${userId}2024`;
            const db = `user_${userId}_db`;
            return `
                <div style="padding: 0.75rem; background: rgba(16, 185, 129, 0.1); border: 1px solid rgba(16, 185, 129, 0.2); border-radius: var(--radius-md); margin: 0.5rem 0;">
                    <div style="font-weight: bold; color: var(--success-color); margin-bottom: 0.5rem;">MySQL</div>
                    <div style="display: grid; grid-template-columns: repeat(2, minmax(120px, 1fr)); gap: 0.5rem; font-size: 0.8rem; color: var(--text-secondary);">
                        <div><strong>host:</strong> ${host}</div>
                        <div><strong>port:</strong> ${port}</div>
                        <div><strong>account:</strong> ${account}</div>
                        <div><strong>password:</strong> ${password}</div>
                        <div style="grid-column: 1 / -1;"><strong>db:</strong> ${db}</div>
                    </div>
                </div>
            `;
        }

        function extractHost(url) {
            try { return new URL(url).hostname; } catch (_) { return null; }
        }
        function extractPort(url) {
            try { return new URL(url).port; } catch (_) { return null; }
        }

        // 快速操作
        function showQuickCreate(envType) {
            // 为所有快速操作卡片添加loading状态
            const allCards = document.querySelectorAll('.quick-action-card');
            allCards.forEach(card => card.classList.add('loading'));
            
            // 延迟执行，让用户看到loading效果
            setTimeout(() => {
                // 移除loading状态
                allCards.forEach(card => card.classList.remove('loading'));
                
                // 设置环境类型
                document.getElementById('envType').value = envType;
                document.getElementById('envUserId').focus();
                showMessage(`已选择环境类型: ${getEnvironmentTypeText(envType)}`, 'success');
                
                // 显示快速创建提示
                showEnvironmentProgress(true, '快速创建模式', `已选择 ${getEnvironmentTypeText(envType)} 环境类型，请在下方输入用户ID并点击"创建环境"按钮`, false);
                
                // 3秒后自动隐藏提示
                setTimeout(() => {
                    showEnvironmentProgress(false);
                }, 3000);
            }, 800); // 800ms的loading效果
        }

        // 为特定用户快速创建环境
        async function quickCreateForUser(userId, role) {
            console.log('快速创建环境被调用:', { userId, role });
            // 显示选择环境类型的下拉选择对话框
            const envType = await showEnvironmentTypeDialog(userId, role);
            
            if (!envType) {
                return; // 用户取消选择
            }

            // 确保模态对话框已关闭
            closeEnvironmentTypeModal();

            // 添加小延迟确保模态对话框完全关闭
            await new Promise(resolve => setTimeout(resolve, 100));

            // 显示创建进度
            showEnvironmentProgress(true, '正在快速创建环境...', `正在为用户 ${userId} 创建 ${getEnvironmentTypeText(envType.toUpperCase())} 环境，请稍候...`, true);
            
            // 启动进度模拟
            const progressInterval = simulateEnvironmentProgress();

            try {
                const response = await fetch(`${API_BASE}/${userId}/environment/selective?userRole=${role}&environmentTypes=${envType.toUpperCase()}`, {
                    method: 'POST'
                });

                // 停止进度模拟
                clearInterval(progressInterval);
                updateEnvironmentProgress(100);

                if (response.ok) {
                    const environment = await response.json();
                    let message = `用户 ${userId} 环境创建成功！类型: ${getEnvironmentTypeText(envType.toUpperCase())}`;
                    if (environment.ideUrl) message += ` IDE地址: ${environment.ideUrl}`;
                    if (environment.jupyterUrl) message += ` Jupyter地址: ${environment.jupyterUrl}`;
                    if (environment.virtualDesktopUrl) message += ` 虚拟桌面地址: ${environment.virtualDesktopUrl}`;
                    
                    // 显示成功状态
                    showEnvironmentProgress(true, '✅ 快速环境创建成功！', message, false);
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showEnvironmentProgress(false);
                    }, 3000);
                    
                    showMessage(message, 'success');
                    loadUsers();
                    loadStats();
                } else {
                    // 显示失败状态
                    showEnvironmentProgress(true, '❌ 快速环境创建失败！', '请检查用户ID和权限设置', false);
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showEnvironmentProgress(false);
                    }, 3000);
                    
                    showMessage(`用户 ${userId} 环境创建失败！`, 'error');
                }
            } catch (error) {
                // 停止进度模拟
                clearInterval(progressInterval);
                
                // 显示错误状态
                showEnvironmentProgress(true, '❌ 快速创建环境时发生错误', error.message, false);
                
                // 3秒后隐藏进度显示
                setTimeout(() => {
                    showEnvironmentProgress(false);
                }, 3000);
                
                showMessage(`为用户 ${userId} 创建环境时发生错误: ` + error.message, 'error');
            }
        }

        // 管理用户
        async function manageUser(userId, action) {
            try {
                let response;
                let actionText = '';
                
                // 显示操作进度
                switch (action) {
                    case 'start':
                        actionText = '启动环境';
                        showEnvironmentProgress(true, '正在启动环境...', `正在启动用户 ${userId} 的环境，请稍候...`, false);
                        response = await fetch(`${API_BASE}/${userId}/environment/start`, { method: 'POST' });
                        break;
                    case 'stop':
                        actionText = '停止环境';
                        showEnvironmentProgress(true, '正在停止环境...', `正在停止用户 ${userId} 的环境，请稍候...`, false);
                        response = await fetch(`${API_BASE}/${userId}/environment/stop`, { method: 'POST' });
                        break;
                    case 'delete':
                        if (!confirm('确定要删除该用户吗？')) return;
                        actionText = '删除用户';
                        showEnvironmentProgress(true, '正在删除用户...', `正在删除用户 ${userId}，请稍候...`, false);
                        response = await fetch(`${API_BASE}/${userId}`, { method: 'DELETE' });
                        break;
                }

                if (response && response.ok) {
                    const result = await response.json();
                    
                    // 显示成功状态
                    showEnvironmentProgress(true, `✅ ${actionText}成功！`, result.message || '操作成功', false);
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showEnvironmentProgress(false);
                    }, 3000);
                    
                    showMessage(result.message || '操作成功', 'success');
                    loadUsers();
                    loadStats();
                } else {
                    // 显示失败状态
                    showEnvironmentProgress(true, `❌ ${actionText}失败！`, '请检查用户ID和权限设置', false);
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showEnvironmentProgress(false);
                    }, 3000);
                    
                    showMessage(`${actionText}失败！`, 'error');
                }
            } catch (error) {
                // 显示错误状态
                showEnvironmentProgress(true, `❌ ${actionText}时发生错误`, error.message, false);
                
                // 3秒后隐藏进度显示
                setTimeout(() => {
                    showEnvironmentProgress(false);
                }, 3000);
                
                showMessage(`操作失败: ${error.message}`, 'error');
            }
        }

        // 查看用户详情
        async function viewUserDetails(userId) {
            try {
                const response = await fetch(`${API_BASE}/${userId}/environment`);
                if (response.ok) {
                    const environment = await response.json();
                    const envTypesText = environment.environmentTypes ? 
                        environment.environmentTypes.map(type => getEnvironmentTypeText(type)).join(', ') : '未知';
                    
                    let details = `用户环境详情:\n`;
                    details += `用户ID: ${environment.userId}\n`;
                    details += `环境ID: ${environment.environmentId}\n`;
                    details += `状态: ${environment.status}\n`;
                    details += `环境类型: ${envTypesText}\n`;
                    details += `创建时间: ${environment.createdAt}\n\n`;
                    
                    if (environment.ideUrl) {
                        details += `IDE访问地址: ${environment.ideUrl}\n`;
                        details += `IDE端口: ${environment.idePort}\n`;
                        details += `IDE密码: ${environment.idePassword}\n\n`;
                    }
                    
                    if (environment.jupyterUrl) {
                        details += `Jupyter访问地址: ${environment.jupyterUrl}\n`;
                        details += `Jupyter端口: ${environment.jupyterPort}\n`;
                        details += `Jupyter Token: ${environment.jupyterToken}\n`;
                    }
                    
                    alert(details);
                } else {
                    showMessage('获取用户详情失败', 'error');
                }
            } catch (error) {
                showMessage('获取用户详情时发生错误: ' + error.message, 'error');
            }
        }

        // 加载统计信息
        async function loadStats() {
            try {
                const response = await fetch(`${API_BASE}/stats`);
                if (response.ok) {
                    const stats = await response.json();
                    document.getElementById('totalUsers').textContent = stats.totalUsers;
                    document.getElementById('activeUsers').textContent = stats.activeUsers;
                    document.getElementById('runningEnvironments').textContent = stats.runningEnvironments;
                    document.getElementById('stoppedEnvironments').textContent = stats.stoppedEnvironments;
                } else {
                    throw new Error('加载统计信息失败');
                }
            } catch (error) {
                console.error('加载统计信息失败:', error);
                throw error; // 重新抛出错误，让调用者处理
            }
        }

        // 显示消息
        function showMessage(message, type) {
            const messageArea = document.getElementById('messageArea');
            const messageDiv = document.createElement('div');
            messageDiv.className = `message ${type}`;
            messageDiv.textContent = message;
            messageArea.appendChild(messageDiv);

            // 3秒后自动移除消息
            setTimeout(() => {
                messageDiv.remove();
            }, 3000);
        }

        // 环境类型选择模态对话框相关函数
        let currentQuickCreateUserId = null;
        let currentQuickCreateRole = null;

        function showEnvironmentTypeDialog(userId, role) {
            return new Promise((resolve) => {
                try {
                    currentQuickCreateUserId = userId;
                    currentQuickCreateRole = role;
                    
                    const modalUserId = document.getElementById('modalUserId');
                    const modalEnvType = document.getElementById('modalEnvType');
                    const modal = document.getElementById('environmentTypeModal');
                    
                    if (!modalUserId || !modalEnvType || !modal) {
                        console.error('模态对话框元素未找到:', { modalUserId, modalEnvType, modal });
                        resolve(null);
                        return;
                    }
                    
                    modalUserId.textContent = userId;
                    modalEnvType.value = 'BOTH'; // 默认选择
                    
                    console.log('显示模态对话框:', modal);
                    console.log('模态对话框的类名:', modal.className);
                    console.log('模态对话框的样式:', modal.style.cssText);
                    
                    modal.style.display = 'block';
                    console.log('模态对话框显示状态:', modal.style.display);
                    
                    // 强制重新计算样式
                    modal.offsetHeight;
                    
                    // 检查模态对话框内容
                    const modalContent = modal.querySelector('.modal-content');
                    if (modalContent) {
                        console.log('模态对话框内容元素:', modalContent);
                        console.log('模态对话框内容的样式:', modalContent.style.cssText);
                        console.log('模态对话框内容的计算样式:', window.getComputedStyle(modalContent));
                    } else {
                        console.error('模态对话框内容元素未找到');
                    }
                    
                    // 设置全局变量供确认函数使用
                    window.resolveEnvironmentType = resolve;
                } catch (error) {
                    console.error('显示模态对话框时发生错误:', error);
                    resolve(null);
                }
            });
        }

        function closeEnvironmentTypeModal() {
            try {
                const modal = document.getElementById('environmentTypeModal');
                if (modal) {
                    modal.style.display = 'none';
                    console.log('模态对话框已关闭');
                } else {
                    console.error('模态对话框元素未找到');
                }
                
                if (window.resolveEnvironmentType) {
                    window.resolveEnvironmentType(null); // 返回null表示用户取消
                    window.resolveEnvironmentType = null;
                }
            } catch (error) {
                console.error('关闭模态对话框时发生错误:', error);
            }
        }

        async function confirmEnvironmentType() {
            try {
                const modalEnvType = document.getElementById('modalEnvType');
                const modal = document.getElementById('environmentTypeModal');
                
                if (!modalEnvType || !modal) {
                    console.error('确认环境类型时元素未找到:', { modalEnvType, modal });
                    return;
                }
                
                const envType = modalEnvType.value;
                console.log('用户选择的环境类型:', envType);
                
                modal.style.display = 'none';
                console.log('模态对话框已关闭');
                
                if (window.resolveEnvironmentType) {
                    window.resolveEnvironmentType(envType);
                    window.resolveEnvironmentType = null;
                }
            } catch (error) {
                console.error('确认环境类型时发生错误:', error);
            }
        }

        // 点击模态对话框外部关闭
        document.addEventListener('DOMContentLoaded', function() {
            const modal = document.getElementById('environmentTypeModal');
            console.log('DOM加载完成，模态对话框元素:', modal);
            
            if (modal) {
                modal.addEventListener('click', function(event) {
                    console.log('模态对话框点击事件:', event.target, event.target === modal);
                    if (event.target === modal) {
                        closeEnvironmentTypeModal();
                    }
                });
                
                // 添加键盘支持
                document.addEventListener('keydown', function(event) {
                    if (event.key === 'Escape' && modal.style.display === 'block') {
                        console.log('按下Escape键，关闭模态对话框');
                        closeEnvironmentTypeModal();
                    }
                    if (event.key === 'Enter' && modal.style.display === 'block') {
                        console.log('按下Enter键，确认环境类型');
                        confirmEnvironmentType();
                    }
                });
            } else {
                console.error('模态对话框元素未找到，无法设置事件监听器');
            }
        });

        // 文件上传功能
        async function uploadSingleFile() {
            const userId = document.getElementById('uploadUserId').value;
            const targetDir = document.getElementById('uploadTargetDir').value;
            const fileInput = document.getElementById('singleFile');
            
            if (!userId) {
                showMessage('请输入用户ID', 'error');
                return;
            }
            
            if (!fileInput.files || fileInput.files.length === 0) {
                showMessage('请选择要上传的文件', 'error');
                return;
            }
            
            const file = fileInput.files[0];
            await uploadFile(userId, file, targetDir, 'single');
        }

        async function uploadMultipleFiles() {
            const userId = document.getElementById('uploadUserId').value;
            const targetDir = document.getElementById('uploadTargetDir').value;
            const fileInput = document.getElementById('multipleFiles');
            
            if (!userId) {
                showMessage('请输入用户ID', 'error');
                return;
            }
            
            if (!fileInput.files || fileInput.files.length === 0) {
                showMessage('请选择要上传的文件', 'error');
                return;
            }
            
            const files = Array.from(fileInput.files);
            await uploadFiles(userId, files, targetDir);
        }

        async function uploadFile(userId, file, targetDir, type = 'single') {
            const formData = new FormData();
            formData.append('file', file);
            formData.append('targetDirectory', targetDir);
            
            // 显示上传进度，包含进度条
            showUploadProgress(true, `正在上传文件: ${file.name}...`, true);
            
            // 启动进度模拟
            const progressInterval = simulateUploadProgress();
            
            try {
                const response = await fetch(`/api/user-files/${userId}/upload`, {
                    method: 'POST',
                    body: formData
                });
                
                // 停止进度模拟
                clearInterval(progressInterval);
                updateUploadProgress(100);
                
                if (response.ok) {
                    const result = await response.json();
                    if (result.success) {
                        // 显示成功状态
                        showUploadProgress(true, `✅ 文件上传成功！`, false);
                        
                        // 3秒后隐藏进度显示
                        setTimeout(() => {
                            showUploadProgress(false);
                        }, 3000);
                        
                        showMessage(`文件上传成功！路径: ${result.path}`, 'success');
                        // 清空文件输入
                        if (type === 'single') {
                            document.getElementById('singleFile').value = '';
                        }
                    } else {
                        // 显示失败状态
                        showUploadProgress(true, `❌ 文件上传失败: ${result.message}`, false);
                        
                        // 3秒后隐藏进度显示
                        setTimeout(() => {
                            showUploadProgress(false);
                        }, 3000);
                        
                        showMessage(`文件上传失败: ${result.message}`, 'error');
                    }
                } else {
                    const errorText = await response.text();
                    // 显示失败状态
                    showUploadProgress(true, `❌ 文件上传失败: ${errorText}`, false);
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showUploadProgress(false);
                    }, 3000);
                    
                    showMessage(`文件上传失败: ${errorText}`, 'error');
                }
            } catch (error) {
                // 停止进度模拟
                clearInterval(progressInterval);
                
                // 显示错误状态
                showUploadProgress(true, `❌ 上传文件时发生错误: ${error.message}`, false);
                
                // 3秒后隐藏进度显示
                setTimeout(() => {
                    showUploadProgress(false);
                }, 3000);
                
                showMessage(`上传文件时发生错误: ${error.message}`, 'error');
            }
        }

        async function uploadFiles(userId, files, targetDir) {
            const formData = new FormData();
            files.forEach(file => {
                formData.append('files', file);
            });
            formData.append('targetDirectory', targetDir);
            
            // 显示上传进度，包含进度条
            showUploadProgress(true, `正在批量上传 ${files.length} 个文件...`, true);
            
            // 启动进度模拟
            const progressInterval = simulateUploadProgress();
            
            try {
                const response = await fetch(`/api/user-files/${userId}/upload/batch`, {
                    method: 'POST',
                    body: formData
                });
                
                // 停止进度模拟
                clearInterval(progressInterval);
                updateUploadProgress(100);
                
                if (response.ok) {
                    const result = await response.json();
                    if (result.success) {
                        // 显示成功状态
                        showUploadProgress(true, `✅ 批量上传成功！共上传 ${result.paths.length} 个文件`, false);
                        
                        // 3秒后隐藏进度显示
                        setTimeout(() => {
                            showUploadProgress(false);
                        }, 3000);
                        
                        const pathsText = result.paths.join(', ');
                        showMessage(`批量上传成功！共上传 ${result.paths.length} 个文件`, 'success');
                        // 清空文件输入
                        document.getElementById('multipleFiles').value = '';
                    } else {
                        // 显示失败状态
                        showUploadProgress(true, `❌ 批量上传失败: ${result.message}`, false);
                        
                        // 3秒后隐藏进度显示
                        setTimeout(() => {
                            showUploadProgress(false);
                        }, 3000);
                        
                        showMessage(`批量上传失败: ${result.message}`, 'error');
                    }
                } else {
                    const errorText = await response.text();
                    // 显示失败状态
                    showUploadProgress(true, `❌ 批量上传失败: ${errorText}`, false);
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showUploadProgress(false);
                    }, 3000);
                    
                    showMessage(`批量上传失败: ${errorText}`, 'error');
                }
            } catch (error) {
                // 停止进度模拟
                clearInterval(progressInterval);
                
                // 显示错误状态
                showUploadProgress(true, `❌ 批量上传时发生错误: ${error.message}`, false);
                
                // 3秒后隐藏进度显示
                        setTimeout(() => {
                            showUploadProgress(false);
                        }, 3000);
                
                showMessage(`批量上传时发生错误: ${error.message}`, 'error');
            }
        }

        function showUploadProgress(show, message = '', showProgressBar = false) {
            const progressDiv = document.getElementById('uploadProgress');
            const statusDiv = document.getElementById('uploadStatus');
            const detailsDiv = document.getElementById('uploadDetails');
            const progressBarDiv = document.getElementById('uploadProgressBar');
            
            if (show) {
                progressDiv.style.display = 'block';
                statusDiv.textContent = message;
                detailsDiv.textContent = '请稍候...';
                progressBarDiv.style.display = showProgressBar ? 'block' : 'none';
            } else {
                progressDiv.style.display = 'none';
                statusDiv.textContent = '准备上传...';
                detailsDiv.textContent = '';
                progressBarDiv.style.display = 'none';
                // 重置上传进度条
                updateUploadProgress(0);
            }
        }

        // 更新上传进度
        function updateUploadProgress(percentage) {
            const progressFill = document.getElementById('uploadProgressFill');
            const progressText = document.getElementById('uploadProgressText');
            
            if (progressFill && progressText) {
                progressFill.style.width = `${percentage}%`;
                progressText.textContent = `${Math.round(percentage)}%`;
            }
        }

        // 模拟文件上传进度
        function simulateUploadProgress() {
            let progress = 0;
            const interval = setInterval(() => {
                progress += Math.random() * 20;
                if (progress >= 100) {
                    progress = 100;
                    clearInterval(interval);
                }
                updateUploadProgress(progress);
            }, 300);
            return interval;
        }

        // 显示环境创建进度
        function showEnvironmentProgress(show, status = '', details = '', showProgressBar = false) {
            const progressDiv = document.getElementById('environmentProgress');
            const statusDiv = document.getElementById('environmentStatus');
            const detailsDiv = document.getElementById('environmentDetails');
            const progressBarDiv = document.getElementById('environmentProgressBar');
            
            if (show) {
                progressDiv.style.display = 'block';
                progressDiv.classList.add('environment-progress');
                statusDiv.textContent = status || '正在创建环境...';
                detailsDiv.textContent = details || '请稍候，这可能需要几分钟时间...';
                progressBarDiv.style.display = showProgressBar ? 'block' : 'none';
            } else {
                progressDiv.style.display = 'none';
                progressDiv.classList.remove('environment-progress');
                statusDiv.textContent = '准备创建...';
                detailsDiv.textContent = '';
                progressBarDiv.style.display = 'none';
                // 重置进度条
                updateEnvironmentProgress(0);
            }
        }

        // 更新环境创建进度
        function updateEnvironmentProgress(percentage) {
            const progressFill = document.getElementById('progressFill');
            const progressText = document.getElementById('progressText');
            
            if (progressFill && progressText) {
                progressFill.style.width = `${percentage}%`;
                progressText.textContent = `${Math.round(percentage)}%`;
            }
        }

        // 模拟环境创建进度（实际项目中可以根据后端返回的状态更新）
        function simulateEnvironmentProgress() {
            let progress = 0;
            const interval = setInterval(() => {
                progress += Math.random() * 15;
                if (progress >= 100) {
                    progress = 100;
                    clearInterval(interval);
                }
                updateEnvironmentProgress(progress);
            }, 500);
            return interval;
        }

        // 权限修复功能
        async function fixUserPermissions() {
            const userId = document.getElementById('uploadUserId').value;
            
            if (!userId) {
                showMessage('请输入用户ID', 'error');
                return;
            }
            
            // 显示修复进度，包含进度条
            showUploadProgress(true, '正在修复IDE权限问题...', true);
            
            // 启动进度模拟
            const progressInterval = simulateUploadProgress();
            
            try {
                const response = await fetch(`/api/users/${userId}/fix-permissions`, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    }
                });
                
                // 停止进度模拟
                clearInterval(progressInterval);
                updateUploadProgress(100);
                
                if (response.ok) {
                    const result = await response.json();
                    if (result.success) {
                        // 显示成功状态
                        showUploadProgress(true, '✅ 权限修复成功！IDE容器已重启，请稍等片刻后重试文件操作', false);
                        
                        // 3秒后隐藏进度显示
                        setTimeout(() => {
                            showUploadProgress(false);
                        }, 3000);
                        
                        showMessage('权限修复成功！IDE容器已重启，请稍等片刻后重试文件操作', 'success');
                    } else {
                        // 显示失败状态
                        showUploadProgress(true, `❌ 权限修复失败: ${result.message}`, false);
                        
                        // 3秒后隐藏进度显示
                        setTimeout(() => {
                            showUploadProgress(false);
                        }, 3000);
                        
                        showMessage(`权限修复失败: ${result.message}`, 'error');
                    }
                } else {
                    const errorText = await response.text();
                    // 显示失败状态
                    showUploadProgress(true, `❌ 权限修复失败: ${errorText}`, false);
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showUploadProgress(false);
                    }, 3000);
                    
                    showMessage(`权限修复失败: ${errorText}`, 'error');
                }
            } catch (error) {
                // 停止进度模拟
                clearInterval(progressInterval);
                
                // 显示错误状态
                showUploadProgress(true, `❌ 权限修复时发生错误: ${error.message}`, false);
                
                // 3秒后隐藏进度显示
                setTimeout(() => {
                    showUploadProgress(false);
                }, 3000);
                
                showMessage(`权限修复时发生错误: ${error.message}`, 'error');
            }
        }



        // 为特定用户快速上传文件
        async function quickUploadForUser(userId) {
            // 设置用户ID
            document.getElementById('uploadUserId').value = userId;
            
            // 显示快速上传提示
            showUploadProgress(true, '快速上传模式', `已选择用户 ${userId}，请选择要上传的文件`, false);
            
            // 显示文件选择对话框
            const fileInput = document.createElement('input');
            fileInput.type = 'file';
            fileInput.multiple = true;
            fileInput.accept = '*/*';
            
            fileInput.onchange = function() {
                if (this.files.length === 0) {
                    showUploadProgress(false);
                    return;
                }
                
                const targetDir = prompt(`为用户 ${userId} 选择上传目录:`, '/home/coder/project');
                if (!targetDir) {
                    showUploadProgress(false);
                    return;
                }
                
                document.getElementById('uploadTargetDir').value = targetDir;
                
                if (this.files.length === 1) {
                    // 单文件上传
                    uploadFile(userId, this.files[0], targetDir, 'single');
                } else {
                    // 批量上传
                    uploadFiles(userId, Array.from(this.files), targetDir);
                }
            };
            
            fileInput.click();
        }

        // 文件树功能
        async function loadFileTree() {
            const userId = document.getElementById('treeUserId').value;
            const rootDir = document.getElementById('treeRootDir').value;
            
            if (!userId) {
                showMessage('请输入用户ID', 'error');
                return;
            }
            
            // 显示文件树加载进度
            showEnvironmentProgress(true, '正在加载文件树...', `正在加载用户 ${userId} 的文件树，根目录: ${rootDir}`, false);
            
            showFileTreeLoading(true);
            hideFileTreeError();
            
            try {
                const response = await fetch(`/api/user-files/${userId}/tree?rootDirectory=${encodeURIComponent(rootDir)}`);
                
                if (response.ok) {
                    const treeData = await response.json();
                    displayFileTree(treeData);
                    showFileTreeContainer(true);
                    
                    // 显示成功状态
                    showEnvironmentProgress(true, '✅ 文件树加载成功！', `成功加载 ${treeData.length} 个文件/目录`, false);
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showEnvironmentProgress(false);
                    }, 3000);
                } else {
                    const errorText = await response.text();
                    // 显示失败状态
                    showEnvironmentProgress(true, '❌ 文件树加载失败！', errorText, false);
                    
                    // 3秒后隐藏进度显示
                    setTimeout(() => {
                        showEnvironmentProgress(false);
                    }, 3000);
                    
                    showFileTreeError(`加载文件树失败: ${errorText}`);
                }
            } catch (error) {
                // 显示错误状态
                showEnvironmentProgress(true, '❌ 加载文件树时发生错误', error.message, false);
                
                // 3秒后隐藏进度显示
                setTimeout(() => {
                    showEnvironmentProgress(false);
                }, 3000);
                
                showFileTreeError(`加载文件树时发生错误: ${error.message}`);
            } finally {
                showFileTreeLoading(false);
            }
        }

        function refreshFileTree() {
            // 显示刷新提示
            showEnvironmentProgress(true, '正在刷新文件树...', '正在重新加载文件树，请稍候...', false);
            
            // 延迟执行，让用户看到提示
            setTimeout(() => {
                loadFileTree();
            }, 500);
        }

        function displayFileTree(treeData) {
            const container = document.getElementById('fileTreeContent');
            container.innerHTML = '';
            
            if (treeData.length === 0) {
                container.innerHTML = '<div style="text-align: center; color: #666; padding: 20px;">📁 目录为空</div>';
                return;
            }
            
            treeData.forEach(node => {
                container.appendChild(createFileTreeNode(node, 0));
            });
        }

        // 格式化文件大小的辅助函数
        function getReadableSize(size) {
            if (size < 1024) {
                return size + ' B';
            } else if (size < 1024 * 1024) {
                return (size / 1024).toFixed(1) + ' KB';
            } else if (size < 1024 * 1024 * 1024) {
                return (size / (1024 * 1024)).toFixed(1) + ' MB';
            } else {
                return (size / (1024 * 1024 * 1024)).toFixed(1) + ' GB';
            }
        }

        function createFileTreeNode(node, level) {
            const nodeDiv = document.createElement('div');
            nodeDiv.className = `file-tree-node ${node.isDirectory ? 'directory' : 'file'} ${node.isDirectory ? '' : node.fileType}`;
            nodeDiv.style.marginLeft = `${level * 20}px`;
            
            const icon = document.createElement('span');
            icon.className = 'file-tree-icon';
            icon.textContent = node.isDirectory ? '📁' : getFileIcon(node.fileType);
            
            const name = document.createElement('span');
            name.textContent = node.name;
            
            const details = document.createElement('span');
            details.className = 'file-tree-details';
            if (!node.isDirectory) {
                details.textContent = `${getReadableSize(node.size)} • ${node.fileType}`;
            }
            
            nodeDiv.appendChild(icon);
            nodeDiv.appendChild(name);
            nodeDiv.appendChild(details);
            
            // 添加点击事件
            nodeDiv.onclick = function(e) {
                e.stopPropagation();
                if (node.isDirectory) {
                    toggleDirectory(nodeDiv, node);
                } else {
                    showFileDetails(node);
                }
            };
            
            // 如果有子节点，添加展开/折叠功能
            if (node.isDirectory && node.children && node.children.length > 0) {
                const expandIcon = document.createElement('span');
                expandIcon.className = 'file-tree-icon';
                expandIcon.textContent = '▶';
                expandIcon.style.marginRight = '5px';
                expandIcon.onclick = function(e) {
                    e.stopPropagation();
                    toggleDirectory(nodeDiv, node);
                };
                nodeDiv.insertBefore(expandIcon, icon);
            }
            
            return nodeDiv;
        }

        function getFileIcon(fileType) {
            const icons = {
                'code': '📄',
                'document': '📝',
                'image': '🖼️',
                'video': '🎥',
                'audio': '🎵',
                'archive': '📦',
                'data': '📊',
                'other': '📄'
            };
            return icons[fileType] || '📄';
        }

        function toggleDirectory(nodeDiv, node) {
            const children = nodeDiv.querySelectorAll('.file-tree-node');
            const expandIcon = nodeDiv.querySelector('.file-tree-icon');
            
            if (children.length > 0) {
                // 折叠目录
                children.forEach(child => child.style.display = 'none');
                expandIcon.textContent = '▶';
            } else {
                // 展开目录
                if (node.children && node.children.length > 0) {
                    node.children.forEach(child => {
                        const childNode = createFileTreeNode(child, 1);
                        childNode.style.display = 'block';
                        nodeDiv.appendChild(childNode);
                    });
                    expandIcon.textContent = '▼';
                }
            }
        }

        function showFileDetails(node) {
            const details = `文件详情:\n` +
                          `名称: ${node.name}\n` +
                          `路径: ${node.path}\n` +
                          `大小: ${getReadableSize(node.size)}\n` +
                          `类型: ${node.fileType}\n` +
                          `修改时间: ${node.lastModified ? new Date(node.lastModified).toLocaleString() : '未知'}`;
            
            alert(details);
        }

        function showFileTreeLoading(show) {
            const loading = document.getElementById('fileTreeLoading');
            loading.style.display = show ? 'block' : 'none';
        }

        function showFileTreeContainer(show) {
            const container = document.getElementById('fileTreeContainer');
            container.style.display = show ? 'block' : 'none';
        }

        function showFileTreeError(message) {
            const error = document.getElementById('fileTreeError');
            error.textContent = message;
            error.style.display = 'block';
        }

        function hideFileTreeError() {
            const error = document.getElementById('fileTreeError');
            error.style.display = 'none';
        }

        // 为特定用户快速查看文件树
        function quickViewFileTree(userId) {
            document.getElementById('treeUserId').value = userId;
            loadFileTree();
        }

        // 打开 Monaco Editor 演示页面
        function openMonacoEditor(userId) {
            const uid = userId || document.getElementById('treeUserId')?.value || '';
            const url = uid ? '/monaco-editor/integrated-demo/index.html?userId=' + encodeURIComponent(uid) : '/monaco-editor/integrated-demo/index.html';
            window.open(url, '_blank');
        }
    </script>
</body>
</html> 